summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pear/PEAR/Builder.php194
-rw-r--r--pear/PEAR/Command.php7
-rw-r--r--pear/PEAR/Command/Auth.php22
-rw-r--r--pear/PEAR/Command/Build.php8
-rw-r--r--pear/PEAR/Command/Config.php88
-rw-r--r--pear/PEAR/Command/Install.php12
-rw-r--r--pear/PEAR/Command/Package.php134
-rw-r--r--pear/PEAR/Command/Registry.php151
-rw-r--r--pear/PEAR/Command/Remote.php170
-rw-r--r--pear/PEAR/Common.php5
-rw-r--r--pear/PEAR/Config.php147
-rw-r--r--pear/PEAR/Frontend/CLI.php153
-rw-r--r--pear/PEAR/Installer.php63
-rw-r--r--pear/package-PEAR.xml2
-rw-r--r--pear/scripts/pear.in31
-rw-r--r--pear/tests/pear_config.phpt106
16 files changed, 966 insertions, 327 deletions
diff --git a/pear/PEAR/Builder.php b/pear/PEAR/Builder.php
index 8cf44b5f6d..e67fb7e82f 100644
--- a/pear/PEAR/Builder.php
+++ b/pear/PEAR/Builder.php
@@ -29,8 +29,15 @@ class PEAR_Builder extends PEAR_Common
{
// {{{ properties
- // }}}
+ var $php_api_version = 0;
+ var $zend_module_api_no = 0;
+ var $zend_extension_api_no = 0;
+
+ var $extensions_built = array();
+ var $current_callback = null;
+
+ // }}}
// {{{ constructor
/**
@@ -42,19 +49,67 @@ class PEAR_Builder extends PEAR_Common
*/
function PEAR_Builder(&$ui)
{
- $this->PEAR_Common();
+ parent::PEAR_Common();
$this->setFrontendObject($ui);
}
+ // }}}
+ // {{{ build()
+
+ /**
+ * Build an extension from source. Runs "phpize" in the source
+ * directory, but compiles in a temporary directory
+ * (/var/tmp/pear-build-USER/PACKAGE-VERSION).
+ *
+ * @param string $descfile path to XML package description file
+ *
+ * @param mixed $callback callback function used to report output,
+ * see PEAR_Builder::_runCommand for details
+ *
+ * @return array an array of associative arrays with built files,
+ * format:
+ * array( array( 'file' => '/path/to/ext.so',
+ * 'php_api' => YYYYMMDD,
+ * 'zend_mod_api' => YYYYMMDD,
+ * 'zend_ext_api' => YYYYMMDD ),
+ * ... )
+ *
+ * @access public
+ *
+ * @see PEAR_Builder::_runCommand
+ * @see PEAR_Common::infoFromDescriptionFile
+ */
function build($descfile, $callback = null)
{
+ if (PEAR_OS != 'Unix') {
+ return $this->raiseError("building extensions not supported on this platform");
+ }
if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) {
return $info;
}
- $configure_command = "./configure";
+ $dir = dirname($descfile);
+ $old_cwd = getcwd();
+ if (!@chdir($dir)) {
+ return $this->raiseError("could not chdir to $dir");
+ }
+ $dir = getcwd();
+ $this->current_callback = $callback;
+ $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback'));
+ if (PEAR::isError($err)) {
+ return $err;
+ }
+ if (!$err) {
+ return $this->raiseError("`phpize' failed");
+ }
+
+ // start of interactive part
+ $configure_command = "$dir/configure";
if (isset($info['configure_options'])) {
foreach ($info['configure_options'] as $o) {
- $r = $this->ui->userDialog($o['prompt'], 'text', @$o['default']);
+ list($r) = $this->ui->userDialog('build',
+ array($o['prompt']),
+ array('text'),
+ array(@$o['default']));
if (substr($o['name'], 0, 5) == 'with-' &&
($r == 'yes' || $r == 'autodetect')) {
$configure_command .= " --$o[name]";
@@ -63,44 +118,155 @@ class PEAR_Builder extends PEAR_Common
}
}
}
+ // end of interactive part
+
+ // make configurable
+ $build_basedir = "/var/tmp/pear-build-$_ENV[USER]";
+ $build_dir = "$build_basedir/$info[package]-$info[version]";
+ $this->log(1, "building in $build_dir");
+ if (is_dir($build_dir)) {
+ System::rm("-rf $build_dir");
+ }
+ if (!System::mkDir("-p $build_dir")) {
+ return $this->raiseError("could not create build dir: $build_dir");
+ }
+ $this->addTempFile($build_dir);
if (isset($_ENV['MAKE'])) {
$make_command = $_ENV['MAKE'];
} else {
$make_command = 'make';
}
$to_run = array(
- "phpize",
$configure_command,
$make_command,
);
+ if (!@chdir($build_dir)) {
+ return $this->raiseError("could not chdir to $build_dir");
+ }
foreach ($to_run as $cmd) {
$err = $this->_runCommand($cmd, $callback);
- if (PEAR::isError($err)) {
+ if (PEAR::isError($err) && !$err) {
+ chdir($old_cwd);
return $err;
}
- if (!$err) {
- break;
- }
}
- return true;
+ if (!($dp = opendir("modules"))) {
+ chdir($old_cwd);
+ return $this->raiseError("no `modules' directory found");
+ }
+ $built_files = array();
+ while ($ent = readdir($dp)) {
+ if ($ent{0} == '.' || substr($ent, -3) == '.la') {
+ continue;
+ }
+ // harvest!
+ if (@copy("modules/$ent", "$dir/$ent")) {
+ $built_files[] = array(
+ 'file' => "$dir/$ent",
+ 'php_api' => $this->php_api_version,
+ 'zend_mod_api' => $this->zend_module_api_no,
+ 'zend_ext_api' => $this->zend_extension_api_no,
+ );
+ $this->log(1, "$ent copied to $dir/$ent");
+ } else {
+ chdir($old_cwd);
+ return $this->raiseError("failed copying $ent to $dir");
+ }
+ }
+ closedir($dp);
+ chdir($old_cwd);
+ return $built_files;
}
// }}}
+ // {{{ phpizeCallback()
+
+ /**
+ * Message callback function used when running the "phpize"
+ * program. Extracts the API numbers used. Ignores other message
+ * types than "cmdoutput".
+ *
+ * @param string $what the type of message
+ * @param mixed $data the message
+ *
+ * @return void
+ *
+ * @access public
+ */
+ function phpizeCallback($what, $data)
+ {
+ if ($what != 'cmdoutput') {
+ return;
+ }
+ $this->log(3, rtrim($data));
+ if (preg_match('/You should update your .aclocal.m4/', $data)) {
+ return;
+ }
+ $matches = array();
+ if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
+ $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
+ $apino = (int)$matches[2];
+ if (isset($this->$member)) {
+ $this->$member = $apino;
+ $msg = sprintf("%-22s : %d", $matches[1], $apino);
+ $this->log(1, $msg);
+ }
+ }
+ }
+ // }}}
+ // {{{ _runCommand()
+ /**
+ * Run an external command, using a message callback to report
+ * output. The command will be run through popen and output is
+ * reported for every line with a "cmdoutput" message with the
+ * line string, including newlines, as payload.
+ *
+ * @param string $command the command to run
+ *
+ * @param mixed $callback (optional) function to use as message
+ * callback
+ *
+ * @return bool whether the command was successful (exit code 0
+ * means success, any other means failure)
+ *
+ * @access private
+ */
function _runCommand($command, $callback = null)
{
- $pp = @popen($command, "r");
+ $this->log(1, "running: $command");
+ $pp = @popen("$command 2>&1", "r");
if (!$pp) {
return $this->raiseError("failed to run `$command'");
}
while ($line = fgets($pp, 1024)) {
- call_user_func($callback, 'output', $line);
+ if ($callback) {
+ call_user_func($callback, 'cmdoutput', $line);
+ } else {
+ $this->log(2, rtrim($line));
+ }
+ }
+ $exitcode = @pclose($pp);
+ return ($exitcode == 0);
+ }
+
+ // }}}
+ // {{{ log()
+
+ function log($level, $msg)
+ {
+ if ($this->current_callback) {
+ if ($this->debug >= $level) {
+ call_user_func($this->current_callback, 'output', $msg);
+ }
+ return;
}
- pclose($pp);
- return true;
+ return PEAR_Common::log($level, $msg);
}
+
+ // }}}
}
?>
diff --git a/pear/PEAR/Command.php b/pear/PEAR/Command.php
index ecacc8006f..8eea62468a 100644
--- a/pear/PEAR/Command.php
+++ b/pear/PEAR/Command.php
@@ -145,13 +145,18 @@ class PEAR_Command
*/
function &setFrontendClass($uiclass)
{
+ if (is_object($GLOBALS['_PEAR_Command_uiobject']) &&
+ strtolower($GLOBALS['_PEAR_Command_uiclass']) ==
+ get_class($GLOBALS['_PEAR_Command_uiobject'])) {
+ return;
+ }
$file = str_replace('_', '/', $uiclass) . '.php';
@include_once $file;
if (class_exists(strtolower($uiclass))) {
$obj = &new $uiclass;
// quick test to see if this class implements a few of the most
// important frontend methods
- if (method_exists($obj, 'displayLine') && method_exists($obj, 'userConfirm')) {
+ if (method_exists($obj, 'userConfirm')) {
$GLOBALS['_PEAR_Command_uiobject'] = &$obj;
$GLOBALS['_PEAR_Command_uiclass'] = $uiclass;
return $obj;
diff --git a/pear/PEAR/Command/Auth.php b/pear/PEAR/Command/Auth.php
index 1035a1a2de..47f0abf67f 100644
--- a/pear/PEAR/Command/Auth.php
+++ b/pear/PEAR/Command/Auth.php
@@ -87,20 +87,28 @@ password from your user configuration.',
if (empty($username)) {
$username = @$_ENV['USER'];
}
- $this->ui->displayLine("Logging in to $server.");
- $username = trim($this->ui->userDialog('Username', 'text', $username));
-
+ $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);
- $password = trim($this->ui->userDialog('Password', 'password'));
$this->config->set('password', $password);
+
$remote->expectError(401);
$ok = $remote->call('logintest');
$remote->popExpect();
if ($ok === true) {
- $this->ui->displayLine("Logged in.");
+ $this->ui->outputData("Logged in.", $command);
$this->config->store();
} else {
- $this->ui->displayLine("Login failed!");
+ return $this->raiseError("Login failed!");
}
}
@@ -122,7 +130,7 @@ password from your user configuration.',
function doLogout($command, $options, $params)
{
$server = $this->config->get('master_server');
- $this->ui->displayLine("Logging out from $server.");
+ $this->ui->outputData("Logging out from $server.", $command);
$this->config->remove('username');
$this->config->remove('password');
$this->config->store();
diff --git a/pear/PEAR/Command/Build.php b/pear/PEAR/Command/Build.php
index ee03d09201..5b15d3c0cb 100644
--- a/pear/PEAR/Command/Build.php
+++ b/pear/PEAR/Command/Build.php
@@ -56,6 +56,7 @@ Builds one or more extensions contained in a package.'
$params[0] = 'package.xml';
}
$builder = &new PEAR_Builder($this->ui);
+ $this->verbose = $this->config->get('verbose');
$err = $builder->build($params[0], array(&$this, 'buildCallback'));
if (PEAR::isError($err)) {
return $err;
@@ -65,10 +66,9 @@ Builds one or more extensions contained in a package.'
function buildCallback($what, $data)
{
- switch ($what) {
- case 'output':
- $this->ui->displayLine(rtrim($data));
- break;
+ if (($what == 'cmdoutput' && $this->verbose > 1) ||
+ ($what == 'output' && $this->verbose > 0)) {
+ $this->ui->outputData(rtrim($data), 'build');
}
}
}
diff --git a/pear/PEAR/Command/Config.php b/pear/PEAR/Command/Config.php
index ff429e85d1..296119e286 100644
--- a/pear/PEAR/Command/Config.php
+++ b/pear/PEAR/Command/Config.php
@@ -46,8 +46,7 @@ configuration layers are "user", "system" and "default".
'function' => 'doConfigGet',
'shortcut' => 'cg',
'options' => array(),
- 'doc' => '<parameter> [layer]
-Displays the value of one configuration parameter. The
+ 'doc' => '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
@@ -60,8 +59,7 @@ just specified.
'function' => 'doConfigSet',
'shortcut' => 'cs',
'options' => array(),
- 'doc' => '<parameter> <new-value> [layer]
-Sets the value of one configuration parameter. The first
+ 'doc' => '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 be subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional third
@@ -69,16 +67,6 @@ argument may be used to specify which layer to set the configuration parameter
in. The default layer is "user".
',
),
- 'config-help' => array(
- 'summary' => 'Show Information About Setting',
- 'function' => 'doConfigHelp',
- 'shortcut' => 'ch',
- 'options' => array(),
- 'doc' => '[parameter]
-Displays help for a configuration parameter. Without arguments it
-displays help for all configuration parameters.
-',
- ),
);
/**
@@ -99,25 +87,21 @@ displays help for all configuration parameters.
}
$keys = $this->config->getKeys();
sort($keys);
- $this->ui->startTable(array('caption' => 'Configuration:'));
+ $data = array('caption' => 'Configuration:');
foreach ($keys as $key) {
$type = $this->config->getType($key);
$value = $this->config->get($key, @$params[0]);
if ($type == 'password' && $value) {
$value = '********';
- } elseif ($key == 'umask') {
- $value = sprintf("%03o", $value);
}
- if ($value === null || $value === '') {
- $value = '<not set>';
- } elseif ($value === false) {
+ if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
- $this->ui->tableRow(array($key, $value));
+ $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
}
- $this->ui->endTable();
+ $this->ui->outputData($data, $command);
return true;
}
@@ -131,10 +115,10 @@ displays help for all configuration parameters.
if (sizeof($params) < 1 || sizeof($params) > 2) {
return $this->raiseError("config-get expects 1 or 2 parameters");
} elseif (sizeof($params) == 1) {
- $this->ui->displayLine("$params[0] = " . $this->config->get($params[0]));
+ $this->ui->outputData("$params[0]=" . $this->config->get($params[0]), $command);
} else {
- $this->ui->displayLine("($params[1])$params[0] = " .
- $this->config->get($params[0], $params[1]));
+ $data = "$params[1].$params[0]=" .$this->config->get($params[0], $params[1]);
+ $this->ui->outputData($data, $command);
}
return true;
}
@@ -145,52 +129,26 @@ displays help for all configuration parameters.
// $param[1] -> the value for the parameter
// $param[2] -> the layer
$failmsg = '';
- do {
- if (sizeof($params) < 2 || sizeof($params) > 3) {
- $failmsg .= "config-set expects 2 or 3 parameters";
- break;
- }
- if ($error = $this->_checkLayer(@$params[2])) {
- $failmsg .= $error;
- break;
- }
- if ($params[0] == 'umask') {
- list($params[1]) = sscanf($params[1], '%o');
- }
- if (!call_user_func_array(array(&$this->config, 'set'), $params))
- {
- $failmsg = "config-set (" . implode(", ", $params) . ") failed";
- } else {
- $this->config->store();
- }
- } while (false);
+ if (sizeof($params) < 2 || sizeof($params) > 3) {
+ $failmsg .= "config-set expects 2 or 3 parameters";
+ return PEAR::raiseError($failmsg);
+ }
+ if ($error = $this->_checkLayer(@$params[2])) {
+ $failmsg .= $error;
+ return PEAR::raiseError($failmsg);
+ }
+ if (!call_user_func_array(array(&$this->config, 'set'), $params))
+ {
+ $failmsg = "config-set (" . implode(", ", $params) . ") failed";
+ } else {
+ $this->config->store();
+ }
if ($failmsg) {
return $this->raiseError($failmsg);
}
return true;
}
- function doConfigHelp($command, $options, $params)
- {
- if (empty($params)) {
- $params = $this->config->getKeys();
- }
- $this->ui->startTable();
- $this->ui->tableRow(array('Name', 'Type', 'Description'),
- array('bold' => true));
- foreach ($params as $name) {
- $type = $this->config->getType($name);
- $docs = $this->config->getDocs($name);
- if ($type == 'set') {
- $docs = rtrim($docs) . "\nValid set: " .
- implode(' ', $this->config->getSetValues($name));
- }
- $this->ui->tableRow(array($name, $type, $docs), null,
- array(2 => array('wrap' => 50)));
- }
- $this->ui->endTable();
- }
-
/**
* Checks if a layer is defined or not
*
diff --git a/pear/PEAR/Command/Install.php b/pear/PEAR/Command/Install.php
index a2a1fc4373..cabd97ff1f 100644
--- a/pear/PEAR/Command/Install.php
+++ b/pear/PEAR/Command/Install.php
@@ -148,11 +148,8 @@ specified at once.
function doInstall($command, $options, $params)
{
- if (sizeof($params) < 1) {
- return $this->raiseError('Missing package to install. Try "help install"');
- }
if (empty($this->installer)) {
- $this->installer = &new PEAR_Installer($ui);
+ $this->installer = &new PEAR_Installer($this->ui);
}
if ($command == 'upgrade') {
$options[$command] = true;
@@ -163,23 +160,24 @@ specified at once.
if (is_array($info)) {
if ($this->config->get('verbose') > 0) {
$label = "$info[package] $info[version]";
- $this->ui->displayLine("$command ok: $label");
+ $this->ui->outputData("$command ok: $label", $command);
}
} else {
return $this->raiseError("$command failed");
}
}
+ return true;
}
function doUninstall($command, $options, $params)
{
if (empty($this->installer)) {
- $this->installer = &new PEAR_Installer($ui);
+ $this->installer = &new PEAR_Installer($this->ui);
}
foreach ($params as $pkg) {
if ($this->installer->uninstall($pkg, $options)) {
if ($this->config->get('verbose') > 0) {
- $this->ui->displayLine("uninstall ok");
+ $this->ui->outputData("uninstall ok", $command);
}
} else {
return $this->raiseError("uninstall failed");
diff --git a/pear/PEAR/Command/Package.php b/pear/PEAR/Command/Package.php
index 08a05eeb3d..5a5814b924 100644
--- a/pear/PEAR/Command/Package.php
+++ b/pear/PEAR/Command/Package.php
@@ -63,6 +63,15 @@ Creates a PEAR package from its description file (usually called
package.xml).
'
),
+ 'package-info' => array(
+ 'summary' => 'Display information about a package file',
+ 'function' => 'doPackageInfo',
+ 'shortcut' => 'pi',
+ 'options' => array(),
+ 'doc' => '
+Extracts information from a package file and displays it.
+',
+ ),
'package-validate' => array(
'summary' => 'Validate Package Consistency',
'function' => 'doPackageValidate',
@@ -118,6 +127,7 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).',
List all depencies the package has.'
),
);
+ var $output;
/**
* PEAR_Command_Package constructor.
@@ -132,15 +142,15 @@ List all depencies the package has.'
function _displayValidationResults($err, $warn, $strict = false)
{
foreach ($err as $e) {
- $this->ui->displayLine("Error: $e");
+ $this->output .= "Error: $e\n";
}
foreach ($warn as $w) {
- $this->ui->displayLine("Warning: $w");
+ $this->output .= "Warning: $w\n";
}
- $this->ui->displayLine(sprintf('Validation: %d error(s), %d warning(s)',
- sizeof($err), sizeof($warn)));
+ $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
+ sizeof($err), sizeof($warn));
if ($strict && sizeof($err) > 0) {
- $this->ui->displayLine("Fix these errors and try again.");
+ $this->output .= "Fix these errors and try again.";
return false;
}
return true;
@@ -148,6 +158,7 @@ List all depencies the package has.'
function doPackage($command, $options, $params)
{
+ $this->output = '';
include_once 'PEAR/Packager.php';
$pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
ob_start();
@@ -158,32 +169,113 @@ List all depencies the package has.'
$err = $warn = array();
$packager->validatePackageInfo($pkginfofile, $err, $warn);
if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
return;
}
$compress = empty($options['Z']) ? true : false;
$result = $packager->Package($pkginfofile, $compress);
- $output = ob_get_contents();
+ $this->output .= ob_get_contents();
ob_end_clean();
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['n'])) {
- $this->ui->displayLine($result);
+ $this->output .= $result."\n";
return;
}
$lines = explode("\n", $output);
foreach ($lines as $line) {
- $this->ui->displayLine($line);
+ $this->output .= $line."n";
}
if (PEAR::isError($result)) {
- $this->ui->displayLine("Package failed: ".$result->getMessage());
+ $this->output .= "Package failed: ".$result->getMessage();
+ }
+ $this->ui->outputData($this->output, $command);
+ return true;
+ }
+
+ function doPackageInfo($command, $options, $params)
+ {
+ // $params[0] -> the PEAR package to list its information
+ if (sizeof($params) != 1) {
+ return $this->raiseError("bad parameter(s), try \"help $command\"");
+ }
+
+ $obj = new PEAR_Common();
+ if (PEAR::isError($info = $obj->infoFromTgzFile($params[0]))) {
+ return $info;
+ }
+ unset($info['filelist']);
+ unset($info['changelog']);
+ $keys = array_keys($info);
+ $longtext = array('description', 'summary');
+ foreach ($keys as $key) {
+ if (is_array($info[$key])) {
+ switch ($key) {
+ case 'maintainers': {
+ $i = 0;
+ $mstr = '';
+ foreach ($info[$key] as $m) {
+ if ($i++ > 0) {
+ $mstr .= "\n";
+ }
+ $mstr .= $m['name'] . " <";
+ if (isset($m['email'])) {
+ $mstr .= $m['email'];
+ } else {
+ $mstr .= $m['handle'] . '@php.net';
+ }
+ $mstr .= "> ($m[role])";
+ }
+ $info[$key] = $mstr;
+ break;
+ }
+ case 'release_deps': {
+ $i = 0;
+ $dstr = '';
+ foreach ($info[$key] as $d) {
+ if ($i++ > 0) {
+ $dstr .= ", ";
+ }
+ if (isset($this->_deps_rel_trans[$d['rel']])) {
+ $d['rel'] = $this->_deps_rel_trans[$d['rel']];
+ }
+ $dstr .= "$d[type] $d[rel]";
+ if (isset($d['version'])) {
+ $dstr .= " $d[version]";
+ }
+ }
+ $info[$key] = $dstr;
+ break;
+ }
+ default: {
+ $info[$key] = implode(", ", $info[$key]);
+ break;
+ }
+ }
+ }
+ $info[$key] = trim($info[$key]);
+ if (in_array($key, $longtext)) {
+ $info[$key] = preg_replace('/ +/', ' ', $info[$key]);
+ }
+ }
+ $caption = 'About ' . basename($params[0]);
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true);
+ foreach ($info as $key => $value) {
+ $key = ucwords(str_replace('_', ' ', $key));
+ $data['data'][] = array($key, $value);
}
+ $this->ui->outputData($data, $command);
return true;
}
function doPackageValidate($command, $options, $params)
{
+ $this->output = '';
if (sizeof($params) < 1) {
$params[0] = "package.xml";
}
@@ -204,11 +296,14 @@ List all depencies the package has.'
}
$obj->validatePackageInfo($info, $err, $warn);
$this->_displayValidationResults($err, $warn);
+ $this->ui->outputData($this->output, $command);
return true;
}
function doCvsTag($command, $options, $params)
{
+ $this->output = '';
+ $_cmd = $command;
if (sizeof($params) < 1) {
$help = $this->getHelp($command);
return $this->raiseError("$command: missing parameter: $help[0]");
@@ -221,6 +316,7 @@ List all depencies the package has.'
$err = $warn = array();
$obj->validatePackageInfo($info, $err, $warn);
if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
break;
}
$version = $info['version'];
@@ -245,14 +341,15 @@ List all depencies the package has.'
foreach ($files as $file) {
$command .= ' ' . escapeshellarg($file);
}
- $this->ui->displayLine("+ $command");
+ $this->output .= "+ $command\n";
if (empty($options['n'])) {
$fp = popen($command, "r");
while ($line = fgets($fp, 1024)) {
- $this->ui->displayLine(rtrim($line));
+ $this->output .= rtrim($line)."\n";
}
pclose($fp);
}
+ $this->ui->outputData($this->output, $_cmd);
return true;
}
@@ -289,10 +386,11 @@ List all depencies the package has.'
}
if (is_array($info['release_deps'])) {
- $this->ui->startTable(array('caption' => 'Dependencies for ' . $info['package'],
- 'border' => true));
- $this->ui->tableRow(array("Type", "Name", "Relation", "Version"),
- array('bold' => true));
+ $data = array(
+ 'caption' => 'Dependencies for ' . $info['package'],
+ 'border' => true,
+ 'headline' => array("Type", "Name", "Relation", "Version"),
+ );
foreach ($info['release_deps'] as $d) {
@@ -320,15 +418,15 @@ List all depencies the package has.'
$version = '';
}
- $this->ui->tableRow(array($type, $name, $rel, $version), null, array(1 => array('wrap' => 55)));
+ $data['data'][] = array($type, $name, $rel, $version);
}
- $this->ui->endTable();
+ $this->ui->outputData($data, $command);
return true;
}
// Fallback
- $this->ui->displayLine("This package does not have any dependencies.");
+ $this->ui->outputData("This package does not have any dependencies.", $command);
}
}
?> \ No newline at end of file
diff --git a/pear/PEAR/Command/Registry.php b/pear/PEAR/Command/Registry.php
index e9fb0b8fdc..5eeee9befa 100644
--- a/pear/PEAR/Command/Registry.php
+++ b/pear/PEAR/Command/Registry.php
@@ -25,16 +25,9 @@ require_once 'PEAR/Config.php';
class PEAR_Command_Registry extends PEAR_Command_Common
{
+ // {{{ command definitions
+
var $commands = array(
- 'info' => array(
- 'summary' => 'Display information about a package',
- 'function' => 'doInfo',
- 'options' => array(),
- 'doc' => '<pacakge>
-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.',
- ),
'list' => array(
'summary' => 'List Installed Packages',
'function' => 'doList',
@@ -43,7 +36,8 @@ package.',
'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.',
+lists the files in that package.
+',
),
'shell-test' => array(
'summary' => 'Shell Script Test',
@@ -54,10 +48,13 @@ lists the files in that package.',
Tests if a package is installed in the system. Will exit(1) if it is not.
<relation> The version comparison operator. One of:
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
- <version> The version to compare with',
- ),
+ <version> The version to compare with
+'),
);
+ // }}}
+ // {{{ constructor
+
/**
* PEAR_Command_Registry constructor.
*
@@ -68,115 +65,30 @@ Tests if a package is installed in the system. Will exit(1) if it is not.
parent::PEAR_Command_Common($ui, $config);
}
- function doInfo($command, $options, $params)
- {
- // $params[0] -> the PEAR package to list its information
- if (sizeof($params) != 1) {
- return $this->raiseError("bad parameter(s), try \"help $command\"");
- }
-
- if (file_exists($params[0]) && !is_dir($params[0])) {
- $obj = &new PEAR_Common();
- $info = $obj->infoFromAny($params[0]);
- } else {
- $reg = &new PEAR_Registry($this->config->get('php_dir'));
- $info = $reg->packageInfo($params[0]);
- }
-
- if (PEAR::isError($info)) {
- return $info;
- }
- if (empty($info)) {
- $this->ui->displayLine("Nothing found for `$params[0]'");
- return;
- }
-
- unset($info['filelist']);
- unset($info['changelog']);
- $keys = array_keys($info);
- $longtext = array('description', 'summary');
- foreach ($keys as $key) {
- if (is_array($info[$key])) {
- switch ($key) {
- case 'maintainers':
- $i = 0;
- $mstr = '';
- foreach ($info[$key] as $m) {
- if ($i++ > 0) {
- $mstr .= "\n";
- }
- $mstr .= $m['name'] . " <";
- if (isset($m['email'])) {
- $mstr .= $m['email'];
- } else {
- $mstr .= $m['handle'] . '@php.net';
- }
- $mstr .= "> ($m[role])";
- }
- $info[$key] = $mstr;
- break;
- case 'release_deps':
- $i = 0;
- $dstr = '';
- foreach ($info[$key] as $d) {
- if ($i++ > 0) {
- $dstr .= ", ";
- }
- if (isset($this->_deps_rel_trans[$d['rel']])) {
- $d['rel'] = $this->_deps_rel_trans[$d['rel']];
- }
- $dstr .= "$d[type] $d[rel]";
- if (isset($d['version'])) {
- $dstr .= " $d[version]";
- }
- }
- $info[$key] = $dstr;
- break;
- default:
- $info[$key] = implode(", ", $info[$key]);
- break;
- }
- }
- $info[$key] = trim($info[$key]);
- if (in_array($key, $longtext)) {
- $info[$key] = preg_replace('/ +/', ' ', $info[$key]);
- }
- }
- $caption = 'About ' . basename($params[0]);
- $this->ui->startTable(array('caption' => $caption,
- 'border' => true));
- foreach ($info as $key => $value) {
- if ($key{0} == '_') continue;
- $key = ucwords(str_replace('_', ' ', $key));
- $this->ui->tableRow(array($key, $value), null, array(1 => array('wrap' => 55)));
- }
- $this->ui->endTable();
- return true;
- }
+ // }}}
+ // {{{ doList()
function doList($command, $options, $params)
{
- $reg = &new PEAR_Registry($this->config->get('php_dir'));
+ $reg = new PEAR_Registry($this->config->get('php_dir'));
if (sizeof($params) == 0) {
$installed = $reg->packageInfo();
+
$i = $j = 0;
- $this->ui->startTable(
- array('caption' => 'Installed packages:',
- 'border' => true));
+ $data = array(
+ 'caption' => 'Installed packages:',
+ 'border' => true,
+ 'headline' => array('Package', 'Version', 'State')
+ );
foreach ($installed as $package) {
- if ($i++ % 20 == 0) {
- $this->ui->tableRow(
- array('Package', 'Version', 'State'),
- array('bold' => true));
- }
- $this->ui->tableRow(array($package['package'],
+ $data['data'][] = array($package['package'],
$package['version'],
- @$package['release_state']));
+ @$package['release_state']);
}
- if ($i == 0) {
- $this->ui->tableRow(array('(no packages installed)'));
+ if (count($installed)==0) {
+ $data = '(no packages installed)';
}
- $this->ui->endTable();
+ $this->ui->outputData($data, $command);
} else {
if (file_exists($params[0]) && !is_dir($params[0])) {
include_once "PEAR/Common.php";
@@ -201,15 +113,16 @@ Tests if a package is installed in the system. Will exit(1) if it is not.
} else {
$caption = 'Contents of ' . basename($params[0]);
}
- $this->ui->startTable(array('caption' => $caption,
- 'border' => true));
- $this->ui->tableRow($headings, array('bold' => true));
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true,
+ 'headline' => $headings);
foreach ($list as $file => $att) {
if ($installed) {
if (empty($att['installed_as'])) {
continue;
}
- $this->ui->tableRow(array($att['role'], $att['installed_as']));
+ $data['data'][] = array($att['role'], $att['installed_as']);
} else {
if (isset($att['baseinstalldir'])) {
$dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
@@ -236,16 +149,19 @@ Tests if a package is installed in the system. Will exit(1) if it is not.
}
$dest = preg_replace('!/+!', '/', $dest);
$file = preg_replace('!/+!', '/', $file);
- $this->ui->tableRow(array($file, $dest));
+ $data['data'][] = array($file, $dest);
}
}
- $this->ui->endTable();
+ $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'));
@@ -273,6 +189,7 @@ Tests if a package is installed in the system. Will exit(1) if it is not.
}
}
+ // }}}
}
?> \ No newline at end of file
diff --git a/pear/PEAR/Command/Remote.php b/pear/PEAR/Command/Remote.php
index 55f2c354b6..2550236be5 100644
--- a/pear/PEAR/Command/Remote.php
+++ b/pear/PEAR/Command/Remote.php
@@ -22,6 +22,7 @@
require_once 'PEAR/Command/Common.php';
require_once 'PEAR/Common.php';
require_once 'PEAR/Remote.php';
+require_once 'PEAR/Registry.php';
class PEAR_Command_Remote extends PEAR_Command_Common
{
@@ -54,6 +55,24 @@ a newer version is available with the same release state (stable etc.).'
Lists the packages available on the configured server along with the
latest stable release of each package.',
),
+ 'search' => array(
+ 'summary' => 'Search Packagesdatabase',
+ 'function' => 'doSearch',
+ 'shortcut' => 'sp',
+ 'options' => array(),
+ 'doc' => '
+Lists all packages which match the search paramteres (first param
+is package name, second package info)',
+ ),
+ 'list-all' => array(
+ 'summary' => 'List All Packages',
+ 'function' => 'doListAll',
+ 'shortcut' => 'la',
+ 'options' => array(),
+ 'doc' => '
+Lists the packages available on the configured server along with the
+latest stable release of each package.',
+ ),
'download' => array(
'summary' => 'Download Package',
'function' => 'doDownload',
@@ -86,10 +105,36 @@ version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
// }}}
- // {{{ info-remote
+ // {{{ remote-info
- function doInfoRemote($command, $options, $params)
+ function doRemoteInfo($command, $options, $params)
{
+/*
+ return false; // coming soon
+
+ var_dump($params[0]);
+ $r = new PEAR_Remote($this->config);
+ $info = $r->call('package.info', $params[0]);
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ var_dump($info);
+*/
+ $r = new PEAR_Remote($this->config);
+ $available = $r->call('package.listAll', true);
+ if (PEAR::isError($available)) {
+ return $this->raiseError($available);
+ }
+ $info = $available[$params[0]];
+ $info["name"] = $params[0];
+
+ $reg = new PEAR_Registry($this->config->get('php_dir'));
+ $installed = $reg->packageInfo($info['name']);
+ $info['installed'] = $installed['version'];
+
+ $this->ui->outputData($info, $command);
+
return false; // coming soon
}
@@ -104,21 +149,103 @@ version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
return $this->raiseError($available);
}
$i = $j = 0;
- $this->ui->startTable(
- array('caption' => 'Available packages:',
- 'border' => true));
+ $data = array(
+ 'caption' => 'Available packages:',
+ 'border' => true,
+ 'headline' => array('Package', 'Version'),
+ );
foreach ($available as $name => $info) {
- if ($i++ % 20 == 0) {
- $this->ui->tableRow(
- array('Package', 'Version'),
- array('bold' => true));
- }
- $this->ui->tableRow(array($name, $info['stable']));
+ $data['data'][] = array($name, $info['stable']);
+ }
+ if (count($available)==0) {
+ $data = '(no packages installed yet)';
}
- if ($i == 0) {
- $this->ui->tableRow(array('(no packages installed yet)'));
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ // }}}
+ // {{{ list-all
+
+ function doListAll($command, $options, $params)
+ {
+ $r = new PEAR_Remote($this->config);
+ $reg = new PEAR_Registry($this->config->get('php_dir'));
+ $available = $r->call('package.listAll', true);
+ if (PEAR::isError($available)) {
+ return $this->raiseError($available);
+ }
+ $data = array(
+ 'caption' => 'All packages:',
+ 'border' => true,
+ 'headline' => array('Package', 'Latest', 'Local'),
+ );
+
+ foreach ($available as $name => $info) {
+ $installed = $reg->packageInfo($name);
+ $desc = $info['summary'];
+ if (isset($params[$name]))
+ $desc .= "\n\n".$info['description'];
+
+ $data['data'][$info['category']][] = array(
+ $name,
+ $info['stable'],
+ $installed['version'],
+ $desc,
+ );
+ }
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ // }}}
+ // {{{ search
+
+ 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 suppliedy<');
+ };
+
+ $r = new PEAR_Remote($this->config);
+ $reg = new PEAR_Registry($this->config->get('php_dir'));
+ $available = $r->call('package.listAll', true);
+ if (PEAR::isError($available)) {
+ return $this->raiseError($available);
+ }
+ $data = array(
+ 'caption' => 'Matched packages:',
+ 'border' => true,
+ 'headline' => array('Package', '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;
+ };
+
+ $installed = $reg->packageInfo($name);
+ $desc = $info['summary'];
+ if (isset($params[$name]))
+ $desc .= "\n\n".$info['description'];
+
+ $data['data'][$info['category']][] = array(
+ $name,
+ $info['stable'],
+ $installed['version'],
+ $desc,
+ );
}
- $this->ui->endTable();
+ if (!isset($data['data'])) {
+ return $this->raiseError('no packages found');
+ };
+ $this->ui->outputData($data, $command);
return true;
}
@@ -144,7 +271,7 @@ version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
return $this->raiseError($saved);
}
$fname = basename($saved);
- $this->ui->displayLine("File $fname downloaded ($this->bytes_downloaded bytes)");
+ $this->ui->outputData("File $fname downloaded ($this->bytes_downloaded bytes)", $command);
return true;
}
@@ -180,10 +307,11 @@ version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
}
$reg = new PEAR_Registry($this->config->get('php_dir'));
$inst = array_flip($reg->listPackages());
- $this->ui->startTable(array('caption' => $caption,
- 'border' => 1));
- $this->ui->tableRow(array('Package', 'Version', 'Size'),
- array('bold' => true));
+ $data = array(
+ 'caption' => $caption,
+ 'border' => 1,
+ 'headline' => array('Package', 'Version', 'Size'),
+ );
foreach ($latest as $package => $info) {
if (!isset($inst[$package])) {
// skip packages we don't have installed
@@ -204,9 +332,9 @@ version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
} else {
$fs = " -"; // XXX center instead
}
- $this->ui->tableRow(array($package, $version, $fs));
+ $data['data'][] = array($package, $version, $fs);
}
- $this->ui->endTable();
+ $this->ui->outputData($data, $command);
return true;
}
diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php
index 2e33375d63..b75486e1a2 100644
--- a/pear/PEAR/Common.php
+++ b/pear/PEAR/Common.php
@@ -67,7 +67,7 @@ $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src
* Valid replacement types
* @var array
*/
-$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config');
+$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
/**
* Valid "provide" types
@@ -130,6 +130,7 @@ class PEAR_Common extends PEAR
{
parent::PEAR();
$this->config = &PEAR_Config::singleton();
+ $this->debug = $this->config->get('verbose');
}
// }}}
@@ -209,7 +210,7 @@ class PEAR_Common extends PEAR
{
if ($this->debug >= $level) {
if (is_object($this->ui)) {
- $this->ui->displayLine($msg);
+ $this->ui->log($msg);
} else {
print "$msg\n";
}
diff --git a/pear/PEAR/Config.php b/pear/PEAR/Config.php
index d07aeaae28..c37a001dc5 100644
--- a/pear/PEAR/Config.php
+++ b/pear/PEAR/Config.php
@@ -93,51 +93,80 @@ class PEAR_Config extends PEAR
* @var array layer => array(infotype => value, ...)
*/
var $configuration_info = array(
+ // Internet Access
'master_server' => array(
'type' => 'string',
'default' => 'pear.php.net',
'doc' => 'name of the main PEAR server',
+ 'prompt' => 'PEAR server',
+ 'group' => 'Internet Access',
),
+ 'http_proxy' => array(
+ 'type' => 'string',
+ 'default' => '',
+ 'doc' => 'HTTP proxy (host:port) to use when downloading packages',
+ 'prompt' => 'HTTP Proxy Server Address',
+ 'group' => 'Internet Access',
+ ),
+ // File Locations
'php_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_PHPDIR,
'doc' => 'directory where .php files are installed',
+ 'prompt' => 'PEAR directory',
+ 'group' => 'File Locations',
),
'ext_dir' => array(
'type' => 'directory',
'default' => PEAR_EXTENSION_DIR,
'doc' => 'directory where loadable extensions are installed',
+ 'prompt' => 'PHP extension directory',
+ 'group' => 'File Locations',
),
'doc_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_DOCDIR,
'doc' => 'directory where documentation is installed',
+ 'prompt' => 'PEAR documentation directory',
+ 'group' => 'File Locations',
+ ),
+ 'bin_dir' => array(
+ 'type' => 'directory',
+ 'default' => PEAR_CONFIG_DEFAULT_BINDIR,
+ 'doc' => 'directory where executables are installed',
+ 'prompt' => 'PEAR executables directory',
+ 'group' => 'File Locations',
),
'data_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_DATADIR,
'doc' => 'directory where data files are installed',
+ 'prompt' => 'PEAR data directory',
+ 'group' => 'File Locations (Advanced)',
),
'test_dir' => array(
'type' => 'directory',
'default' => PEAR_CONFIG_DEFAULT_TESTDIR,
'doc' => 'directory where regression tests are installed',
+ 'prompt' => 'PEAR test directory',
+ 'group' => 'File Locations (Advanced)',
),
- 'bin_dir' => array(
- 'type' => 'directory',
- 'default' => PEAR_CONFIG_DEFAULT_BINDIR,
- 'doc' => 'directory where executables are installed',
- ),
+ // Maintainers
'username' => array(
'type' => 'string',
'default' => '',
'doc' => '(maintainers) your PEAR account name',
+ 'prompt' => 'PEAR username (for maintainers)',
+ 'group' => 'Maintainers',
),
'password' => array(
'type' => 'password',
'default' => '',
'doc' => '(maintainers) your PEAR account password',
+ 'prompt' => 'PEAR password (for maintainers)',
+ 'group' => 'Maintainers',
),
+ // Advanced
'verbose' => array(
'type' => 'integer',
'default' => 1,
@@ -146,6 +175,8 @@ class PEAR_Config extends PEAR
1: somewhat quiet
2: verbose
3: debug',
+ 'prompt' => 'Debug Log Level',
+ 'group' => 'Advanced',
),
'preferred_state' => array(
'type' => 'set',
@@ -153,16 +184,15 @@ class PEAR_Config extends PEAR
'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
'valid_set' => array(
'stable', 'beta', 'alpha', 'devel', 'snapshot'),
- ),
- 'http_proxy' => array(
- 'type' => 'string',
- 'default' => '',
- 'doc' => 'HTTP proxy (host:port) to use when downloading packages',
+ 'prompt' => 'Preferred Package State',
+ 'group' => 'Advanced',
),
'umask' => array(
- 'type' => 'int',
+ 'type' => 'mask',
'default' => PEAR_DEFAULT_UMASK,
'doc' => 'umask used when creating files (Unix-like systems only)',
+ 'prompt' => 'Unix file mask',
+ 'group' => 'Advanced',
),
/*
'testset1' => array(
@@ -455,6 +485,10 @@ class PEAR_Config extends PEAR
$data[$key] = base64_encode($data[$key]);
break;
}
+ case 'mask': {
+ $data[$key] = octdec($data[$key]);
+ break;
+ }
}
}
return true;
@@ -489,6 +523,10 @@ class PEAR_Config extends PEAR
$data[$key] = base64_decode($data[$key]);
break;
}
+ case 'mask': {
+ $data[$key] = decoct($data[$key]);
+ break;
+ }
}
}
return true;
@@ -547,10 +585,9 @@ class PEAR_Config extends PEAR
}
extract($this->configuration_info[$key]);
switch ($type) {
- case 'integer': {
+ case 'integer':
$value = (int)$value;
break;
- }
case 'set': {
// If a valid_set is specified, require the value to
// be in the set. If there is no valid_set, accept
@@ -612,6 +649,90 @@ class PEAR_Config extends PEAR
}
return false;
}
+ // }}}
+ // {{{ getPrompt(key)
+
+ /**
+ * Get the short documentation for a config value.
+ *
+ * @param string config key
+ *
+ * @return string short documentation string
+ *
+ * @access public
+ *
+ */
+ function getPrompt($key)
+ {
+ if (isset($this->configuration_info[$key])) {
+ return $this->configuration_info[$key]['prompt'];
+ }
+ return false;
+ }
+ // }}}
+ // {{{ getGroup(key)
+
+ /**
+ * Get the parameter group for a config key.
+ *
+ * @param string config key
+ *
+ * @return string parameter group
+ *
+ * @access public
+ *
+ */
+ function getGroup($key)
+ {
+ if (isset($this->configuration_info[$key])) {
+ return $this->configuration_info[$key]['group'];
+ }
+ return false;
+ }
+
+ // }}}
+ // {{{ getGroups()
+
+ /**
+ * Get the list of parameter groups.
+ *
+ * @return array list of parameter groups
+ *
+ * @access public
+ *
+ */
+ function getGroups()
+ {
+ $tmp = array();
+ foreach ($this->configuration_info as $key => $info) {
+ $tmp[$info['group']] = 1;
+ }
+ return array_keys($tmp);
+ }
+
+ // }}}
+ // {{{ getGroupKeys()
+
+ /**
+ * Get the list of the parameters in a group.
+ *
+ * @param string $group parameter group
+ *
+ * @return array list of parameters in $group
+ *
+ * @access public
+ *
+ */
+ function getGroupKeys($group)
+ {
+ $keys = array();
+ foreach ($this->configuration_info as $key => $info) {
+ if ($info['group'] == $group) {
+ $keys[] = $key;
+ }
+ }
+ return $keys;
+ }
// }}}
// {{{ getSetValues(key)
diff --git a/pear/PEAR/Frontend/CLI.php b/pear/PEAR/Frontend/CLI.php
index f8e928a463..5032d18b58 100644
--- a/pear/PEAR/Frontend/CLI.php
+++ b/pear/PEAR/Frontend/CLI.php
@@ -68,11 +68,24 @@ class PEAR_Frontend_CLI extends PEAR
function displayLine($text)
{
+ trigger_error("Frontend::displayLine deprecated", E_USER_ERROR);
+ }
+
+ function _displayLine($text)
+ {
print "$this->lp$text\n";
}
+ // }}}
+ // {{{ display(text)
+
function display($text)
{
+ trigger_error("Frontend::display deprecated", E_USER_ERROR);
+ }
+
+ function _display($text)
+ {
print $text;
}
@@ -81,7 +94,7 @@ class PEAR_Frontend_CLI extends PEAR
function displayError($eobj)
{
- return $this->displayLine($eobj->getMessage());
+ return $this->_displayLine($eobj->getMessage());
}
// }}}
@@ -89,7 +102,7 @@ class PEAR_Frontend_CLI extends PEAR
function displayFatalError($eobj)
{
- $this->displayError($eobj);
+ $this->_displayError($eobj);
exit(1);
}
@@ -98,6 +111,11 @@ class PEAR_Frontend_CLI extends PEAR
function displayHeading($title)
{
+ trigger_error("Frontend::displayHeading deprecated", E_USER_ERROR);
+ }
+
+ function _displayHeading($title)
+ {
print $this->lp.$this->bold($title)."\n";
print $this->lp.str_repeat("=", strlen($title))."\n";
}
@@ -105,27 +123,36 @@ class PEAR_Frontend_CLI extends PEAR
// }}}
// {{{ userDialog(prompt, [type], [default])
- function userDialog($prompt, $type = 'text', $default = '')
+ function userDialog($command, $prompts, $types = array(), $defaults = array())
{
- if ($type == 'password') {
- system('stty -echo');
- }
- print "$this->lp$prompt ";
- if ($default) {
- print "[$default] ";
- }
- print ": ";
- $fp = fopen("php://stdin", "r");
- $line = fgets($fp, 2048);
- fclose($fp);
- if ($type == 'password') {
- system('stty echo');
- print "\n";
- }
- if ($default && trim($line) == "") {
- return $default;
+ $result = array();
+ if (is_array($prompts)) {
+ $fp = fopen("php://stdin", "r");
+ foreach ($prompts as $key => $prompt) {
+ $type = $types[$key];
+ $default = $defaults[$key];
+ if ($type == 'password') {
+ system('stty -echo');
+ }
+ print "$this->lp$prompt ";
+ if ($default) {
+ print "[$default] ";
+ }
+ print ": ";
+ $line = fgets($fp, 2048);
+ if ($type == 'password') {
+ system('stty echo');
+ print "\n";
+ }
+ if ($default && trim($line) == "") {
+ $result[$key] = $default;
+ } else {
+ $result[$key] = $line;
+ }
+ }
+ fclose($fp);
}
- return $line;
+ return $result;
}
// }}}
@@ -133,6 +160,7 @@ class PEAR_Frontend_CLI extends PEAR
function userConfirm($prompt, $default = 'yes')
{
+ trigger_error("Frontend::userConfirm not yet converted", E_USER_ERROR);
static $positives = array('y', 'yes', 'on', '1');
static $negatives = array('n', 'no', 'off', '0');
print "$this->lp$prompt [$default] : ";
@@ -160,6 +188,11 @@ class PEAR_Frontend_CLI extends PEAR
function startTable($params = array())
{
+ trigger_error("Frontend::startTable deprecated", E_USER_ERROR);
+ }
+
+ function _startTable($params = array())
+ {
$this->omode = 'table';
$params['table_data'] = array();
$params['widest'] = array(); // indexed by column
@@ -173,6 +206,11 @@ class PEAR_Frontend_CLI extends PEAR
function tableRow($columns, $rowparams = array(), $colparams = array())
{
+ trigger_error("Frontend::tableRow deprecated", E_USER_ERROR);
+ }
+
+ function _tableRow($columns, $rowparams = array(), $colparams = array())
+ {
$highest = 1;
for ($i = 0; $i < sizeof($columns); $i++) {
$col = &$columns[$i];
@@ -218,10 +256,15 @@ class PEAR_Frontend_CLI extends PEAR
function endTable()
{
+ trigger_error("Frontend::tableRow deprecated", E_USER_ERROR);
+ }
+
+ function _endTable()
+ {
$this->omode = '';
extract($this->params);
if (!empty($caption)) {
- $this->displayHeading($caption);
+ $this->_displayHeading($caption);
}
if (count($table_data) == 0) {
return;
@@ -253,7 +296,7 @@ class PEAR_Frontend_CLI extends PEAR
}
}
if ($borderline) {
- $this->displayLine($borderline);
+ $this->_displayLine($borderline);
}
for ($i = 0; $i < sizeof($table_data); $i++) {
extract($table_data[$i]);
@@ -297,15 +340,75 @@ class PEAR_Frontend_CLI extends PEAR
$rowtext .= $cellstart . $cell . $cellend;
}
$rowtext .= $rowend;
- $this->displayLine($rowtext);
+ $this->_displayLine($rowtext);
}
}
if ($borderline) {
- $this->displayLine($borderline);
+ $this->_displayLine($borderline);
+ }
+ }
+
+ // }}}
+ // {{{ outputData()
+
+ function outputData($data, $command)
+ {
+ switch ($command)
+ {
+ case 'list-all':
+ $this->_startTable($data);
+ if (isset($data['headline']) && is_array($data['headline']))
+ $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
+
+ foreach($data['data'] as $category) {
+ foreach($category as $pkg) {
+ unset($pkg[3]);
+ $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
+ }
+ };
+ $this->_endTable();
+ break;
+ case 'config-show':
+ $this->_startTable($data);
+ if (isset($data['headline']) && is_array($data['headline']))
+ $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
+
+ foreach($data['data'] as $group) {
+ foreach($group as $value) {
+ if ($value === null || $value === '') {
+ $value = "<not set>";
+ };
+ $this->_tableRow($value, null, array(1 => array('wrap' => 55)));
+ }
+ };
+ $this->_endTable();
+ break;
+ default:
+ if (is_array($data))
+ {
+ $this->_startTable($data);
+ if (isset($data['headline']) && is_array($data['headline']))
+ $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
+ foreach($data['data'] as $row)
+ $this->_tableRow($row);
+ $this->_endTable();
+ } else {
+ $this->_displayLine($data);
+ }
}
}
// }}}
+ // {{{ log(text)
+
+
+ function log($text)
+ {
+ return $this->_displayLine($text);
+ }
+
+
+ // }}}
// {{{ bold($text)
function bold($text)
diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php
index be1540f7a9..a3c8f100d2 100644
--- a/pear/PEAR/Installer.php
+++ b/pear/PEAR/Installer.php
@@ -173,10 +173,10 @@ class PEAR_Installer extends PEAR_Common
case 'script':
$dest_dir = $this->config->get('bin_dir');
break;
+ case 'src':
case 'extsrc':
- // don't install test files for now
- $this->log(2, "$file: no support for building extensions yet");
- return PEAR_INSTALLER_OK;
+ $this->source_files++;
+ return;
default:
break;
}
@@ -223,10 +223,12 @@ class PEAR_Installer extends PEAR_Common
}
} elseif ($a['type'] == 'pear-config') {
$to = $this->config->get($a['to']);
+ } elseif ($a['type'] == 'package-info') {
+ $to = $this->pkginfo[$a['to']];
}
if ($to) {
- $subst_from = $a['from'];
- $subst_to = $to;
+ $subst_from[] = $a['from'];
+ $subst_to[] = $to;
}
}
$this->log(2, "doing ".sizeof($subst_from)." substitution(s) for $dest_file");
@@ -243,10 +245,10 @@ class PEAR_Installer extends PEAR_Common
}
if (!OS_WINDOWS) {
if ($atts['role'] == 'script') {
- $mode = 0777 & ~$this->config->get('umask');
+ $mode = 0777 & ~(int)octdec($this->config->get('umask'));
$this->log(3, "+ chmod +x $dest_file");
} else {
- $mode = 0666 & ~$this->config->get('umask');
+ $mode = 0666 & ~(int)octdec($this->config->get('umask'));
}
if (!@chmod($dest_file, $mode)) {
$this->log(0, "failed to change mode of $dest_file");
@@ -425,6 +427,9 @@ class PEAR_Installer extends PEAR_Common
// info from the package it self we want to access from _installFile
$this->pkginfo = &$pkginfo;
+ // used to determine whether we should build any C code
+ $this->source_files = 0;
+
if (empty($options['register-only'])) {
if (!is_dir($this->config->get('php_dir'))) {
return $this->raiseError("no script destination directory\n",
@@ -451,7 +456,6 @@ class PEAR_Installer extends PEAR_Common
$this->popExpect();
if (PEAR::isError($res)) {
if (empty($options['force'])) {
- print "raising error!\n";
return $this->raiseError($res);
} else {
$this->log(0, "Warning: " . $res->getMessage());
@@ -462,6 +466,33 @@ class PEAR_Installer extends PEAR_Common
unset($pkginfo['filelist'][$file]);
}
}
+
+ if ($this->source_files > 0) {
+ $this->log(1, "$this->source_files source files, building");
+ $bob = &new PEAR_Builder($this->ui);
+ $bob->debug = $this->debug;
+ $built = $bob->build($descfile, array(&$this, '_buildCallback'));
+ if (PEAR::isError($built)) {
+ return $built;
+ }
+ foreach ($built as $ext) {
+ $bn = basename($ext['file']);
+ $this->log(2, "installing $bn");
+ $dest = $this->config->get('ext_dir') .
+ DIRECTORY_SEPARATOR . $bn;
+ $this->log(3, "+ cp $ext[file] ext_dir");
+ if (!@copy($ext['file'], $dest)) {
+ return $this->raiseError("failed to copy $bn to $dest");
+ }
+ $pkginfo['filelist'][$bn] = array(
+ 'role' => 'ext',
+ 'installed_as' => $dest,
+ 'php_api' => $ext['php_api'],
+ 'zend_mod_api' => $ext['zend_mod_api'],
+ 'zend_ext_api' => $ext['zend_ext_api'],
+ );
+ }
+ }
}
// Register that the package is installed -----------------------
@@ -531,6 +562,22 @@ class PEAR_Installer extends PEAR_Common
$this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
break;
}
+ if (method_exists($this->ui, '_downloadCallback'))
+ $this->ui->_downloadCallback($msg, $params);
+ }
+
+ // }}}
+ // {{{ _buildCallback()
+
+ function _buildCallback($what, $data)
+ {
+ switch ($what) {
+
+ }
+ if (($what == 'cmdoutput' && $this->debug > 1) ||
+ ($what == 'output' && $this->debug > 0)) {
+ $this->ui->outputData(rtrim($data), 'build');
+ }
}
// }}}
diff --git a/pear/package-PEAR.xml b/pear/package-PEAR.xml
index 9c6a27cda2..0ec6cacfcc 100644
--- a/pear/package-PEAR.xml
+++ b/pear/package-PEAR.xml
@@ -42,6 +42,7 @@
* new command: "build"
* fix: config-set did not work with "set" parameters
* disable magic_quotes_runtime
+* "install" now builds and installs C extensions
</notes>
<filelist>
<file role="data" name="package.dtd"/>
@@ -79,6 +80,7 @@
<dir name="scripts">
<file baseinstalldir="/" role="script" install-as="pear" name="pear.in">
<replace from="@prefix@/bin" to="PHP_BINDIR" type="php-const"/>
+ <replace from="@pear_version@" to="version" type="package-info"/>
</file>
<file baseinstalldir="/" role="script" platform="windows" name="pear.bat"></file>
</dir>
diff --git a/pear/scripts/pear.in b/pear/scripts/pear.in
index c8a2ed333e..d7d77a3e23 100644
--- a/pear/scripts/pear.in
+++ b/pear/scripts/pear.in
@@ -30,6 +30,10 @@ ob_implicit_flush(true);
ini_set('track_errors', true);
ini_set('html_errors', false);
ini_set('magic_quotes_runtime', false);
+error_reporting(E_ALL & ~E_NOTICE);
+set_error_handler('error_handler');
+
+$pear_package_version = "@pear_version@";
require_once 'PEAR.php';
require_once 'PEAR/Config.php';
@@ -225,7 +229,6 @@ function cmdHelp($command)
" -u foo unset `foo' in the user configuration\n".
" -h, -? display help/usage (this message)\n".
" -V version information\n";
-
} elseif ($command == "shortcuts") {
$sc = PEAR_Command::getShortcuts();
$ret = "Shortcuts:\n";
@@ -235,8 +238,7 @@ function cmdHelp($command)
return $ret;
} elseif ($command == "version") {
- $reg = &new PEAR_Registry($config->get('php_dir'));
- return "PEAR " . $reg->packageInfo('PEAR', 'version');
+ return "PEAR $GLOBALS[pear_package_version]";
} elseif ($help = PEAR_Command::getHelp($command)) {
if (is_string($help)) {
@@ -249,6 +251,29 @@ function cmdHelp($command)
// }}}
+function error_handler($errno, $errmsg, $file, $line, $vars) {
+ if (error_reporting() == 0) {
+ return; // @silenced error
+ }
+ $errortype = array (
+ 1 => "Error",
+ 2 => "Warning",
+ 4 => "Parsing Error",
+ 8 => "Notice",
+ 16 => "Core Error",
+ 32 => "Core Warning",
+ 64 => "Compile Error",
+ 128 => "Compile Warning",
+ 256 => "User Error",
+ 512 => "User Warning",
+ 1024=> "User Notice"
+ );
+ $prefix = $errortype[$errno];
+ $file = basename($file);
+ print "\n$prefix: $errmsg in $file on line $line\n";
+}
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/pear/tests/pear_config.phpt b/pear/tests/pear_config.phpt
index 5478319f73..af67ad9953 100644
--- a/pear/tests/pear_config.phpt
+++ b/pear/tests/pear_config.phpt
@@ -12,27 +12,27 @@ copy("user2.input", "user2.conf");
copy("merge.input", "merge.conf");
PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s\n");
-print "#0 starting up\n";
+print "\n#0 starting up\n";
dump_files();
-print "#1 testing: constructor\n";
+print "\n#1 testing: constructor\n";
$config = new PEAR_Config("user.conf", "system.conf");
dump_array("files", $config->files);
-print "#2 testing: singleton\n";
+print "\n#2 testing: singleton\n";
$o1 = &PEAR_Config::singleton();
$o1->blah = 'blah';
$o2 = &PEAR_Config::singleton();
var_dump($o1->blah);
@var_dump($o2->blah);
-print "#3 testing: readConfigFile\n";
+print "\n#3 testing: readConfigFile\n";
$config->readConfigFile("user2.conf", "user");
dump_config($config);
$config->readConfigFile("user.conf");
dump_config($config);
-print "#4 testing: mergeConfigFile\n";
+print "\n#4 testing: mergeConfigFile\n";
$config->readConfigFile("user2.conf");
dump_config($config, "user");
$config->mergeConfigFile("merge.conf", true);
@@ -44,11 +44,11 @@ $config->readConfigFile("user.conf");
dump_config($config, "user");
$config->mergeConfigFile("merge.conf", true, "xyzzy");
-print "#5 testing: config file version detection\n";
+print "\n#5 testing: config file version detection\n";
$config->readConfigFile("user.conf", "user");
$config->readConfigFile("toonew.conf", "user");
-print "#6 testing: get/set/remove\n";
+print "\n#6 testing: get/set/remove\n";
var_dump($config->get("verbose"));
$config->set("verbose", 100, "system");
var_dump($config->get("verbose"));
@@ -62,21 +62,21 @@ var_dump($config->get("verbose"));
$config->remove("verbose", "system");
var_dump($config->get("verbose"));
-print "#7 testing: getType\n";
+print "\n#7 testing: getType\n";
var_dump($config->getType("__unknown__"));
var_dump($config->getType("verbose"));
var_dump($config->getType("master_server"));
var_dump($config->getType("ext_dir"));
-print "#8 testing: getDocs\n";
+print "\n#8 testing: getDocs\n";
print "master_server: " . $config->getDocs("master_server") . "\n";
-print "#9 testing: getKeys\n";
+print "\n#9 testing: getKeys\n";
$keys = $config->getKeys();
sort($keys);
print implode(" ", $keys) . "\n";
-print "#10 testing: definedBy\n";
+print "\n#10 testing: definedBy\n";
var_dump($config->definedBy("verbose"));
$config->set("verbose", 6, "system");
$config->set("verbose", 3, "user");
@@ -89,23 +89,34 @@ var_dump($config->definedBy("verbose"));
$config->remove("verbose", "system");
var_dump($config->definedBy("verbose"));
-print "#11 testing: isDefined\n";
+print "\n#11 testing: isDefined\n";
var_dump($config->isDefined("php_dir"));
var_dump($config->isDefined("verbose"));
var_dump($config->isDefined("HTTP_GET_VARS"));
var_dump($config->isDefined("query"));
-/*
-print "setting user values\n";
-var_dump($config->set("master_server", "pear.localdomain"));
-var_dump($config->writeConfigFile(null, "user"));
-dumpall();
+print "\n#12 testing: getGroup\n";
+foreach ($keys as $key) {
+ print "$key: ".$config->getGroup($key)."\n";
+}
+
+print "\n#13 testing: getGroups\n";
+$groups = $config->getGroups();
+sort($groups);
+print implode(", ", $groups) . "\n";
+
+print "\n#14 testing: getGroupKeys\n";
+foreach ($groups as $group) {
+ $gk = $config->getGroupKeys($group);
+ sort($gk);
+ print "$group: " . implode(", ", $gk) . "\n";
+}
+
+print "\n#15 testing: getPrompt\n";
+foreach ($keys as $key) {
+ print "$key: ".$config->getPrompt($key)."\n";
+}
-print "going back to defaults\n";
-$config->remove("master_server", "user");
-$config->writeConfigFile(null, "user");
-dumpall();
-*/
//
@@ -167,24 +178,30 @@ function dump_config(&$obj, $layer = null) {
#0 starting up
..system.conf: master_server="pear.php.net"
..user.conf: <empty>
+
#1 testing: constructor
files: system="system.conf" user="user.conf"
+
#2 testing: singleton
string(4) "blah"
string(4) "blah"
+
#3 testing: readConfigFile
user: verbose="2"
system: master_server="pear.php.net"
user: <empty>
system: master_server="pear.php.net"
+
#4 testing: mergeConfigFile
user: verbose="2"
user: verbose="100"
user: verbose="2"
user: <empty>
unknown config file type `xyzzy'
+
#5 testing: config file version detection
toonew.conf: unknown version `2.0'
+
#6 testing: get/set/remove
int(1)
int(100)
@@ -192,24 +209,69 @@ int(2)
int(50)
int(2)
int(1)
+
#7 testing: getType
bool(false)
string(7) "integer"
string(6) "string"
string(9) "directory"
+
#8 testing: getDocs
master_server: name of the main PEAR server
+
#9 testing: getKeys
bin_dir data_dir doc_dir ext_dir http_proxy master_server password php_dir preferred_state test_dir umask username verbose
+
#10 testing: definedBy
string(7) "default"
string(4) "user"
string(4) "user"
string(6) "system"
string(7) "default"
+
#11 testing: isDefined
bool(true)
bool(true)
bool(false)
bool(false)
+
+#12 testing: getGroup
+bin_dir: File Locations
+data_dir: File Locations (Advanced)
+doc_dir: File Locations
+ext_dir: File Locations
+http_proxy: Internet Access
+master_server: Internet Access
+password: Maintainers
+php_dir: File Locations
+preferred_state: Advanced
+test_dir: File Locations (Advanced)
+umask: Advanced
+username: Maintainers
+verbose: Advanced
+
+#13 testing: getGroups
+Advanced, File Locations, File Locations (Advanced), Internet Access, Maintainers
+
+#14 testing: getGroupKeys
+Advanced: preferred_state, umask, verbose
+File Locations: bin_dir, doc_dir, ext_dir, php_dir
+File Locations (Advanced): data_dir, test_dir
+Internet Access: http_proxy, master_server
+Maintainers: password, username
+
+#15 testing: getPrompt
+bin_dir: PEAR executables directory
+data_dir: PEAR data directory
+doc_dir: PEAR documentation directory
+ext_dir: PHP extension directory
+http_proxy: HTTP Proxy Server Address
+master_server: PEAR server
+password: PEAR password (for package maintainers)
+php_dir: PEAR directory
+preferred_state: Preferred Package State
+test_dir: PEAR test directory
+umask: Unix file mask
+username: PEAR username (for package maintainers)
+verbose: Debug Log Level
done