* implemented shortcuts ("pv" for "package-validate" etc.)

do "pear help shortcuts" to see what shortcuts exist
* renamed "list-installed" command to "list" and made it able to
  list the contents of installed packages as well as tar/tgz/xml files
* added some more/better command docs
* fixed up the synopsis part in the help output
* display option parameters (--foo=bar, where bar is specified in
  'shortarg' as for example 'f:bar')
* renamed list-remote-packages to list-remote
* renamed remote-package-info to remote-info
This commit is contained in:
Stig Bakken 2002-05-21 01:27:53 +00:00
parent f208968c9f
commit 7ecfacedad
9 changed files with 359 additions and 174 deletions

View File

@ -27,6 +27,12 @@ require_once "PEAR.php";
*/
$GLOBALS['_PEAR_Command_commandlist'] = array();
/**
* List of shortcuts to common commands.
* @var array shortcut => command
*/
$GLOBALS['_PEAR_Command_shortcuts'] = array();
/**
* Array of command objects
* @var array class => object
@ -105,6 +111,9 @@ class PEAR_Command
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
$class = @$GLOBALS['_PEAR_Command_commandlist'][$command];
if (empty($class)) {
return PEAR::raiseError("unknown command `$command'");
@ -211,6 +220,10 @@ class PEAR_Command
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc;
}
$shortcuts = $GLOBALS['_PEAR_Command_objects'][$class]->getShortcuts();
foreach ($shortcuts as $shortcut => $command) {
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
}
}
return true;
}
@ -231,6 +244,21 @@ class PEAR_Command
return $GLOBALS['_PEAR_Command_commandlist'];
}
/**
* Get the list of command shortcuts.
*
* @return array shortcut => command
*
* @access public
*/
function getShortcuts()
{
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_shortcuts'];
}
/**
* Compiles arguments for getopt.
*

View File

@ -31,22 +31,26 @@ class PEAR_Command_Auth extends PEAR_Command_Common
var $commands = array(
'login' => array(
'summary' => 'Connects and authenticates to remote server',
'shortcut' => 'li',
'function' => 'doLogin',
'options' => array(),
'doc' => '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' => '
Log in to the remote server. 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.',
),
'logout' => array(
'summary' => 'Logs out from the remote server',
'shortcut' => 'lo',
'function' => 'doLogout',
'options' => array(),
'doc' => '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' => '
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.',
)
);

View File

@ -71,6 +71,25 @@ class PEAR_Command_Common extends PEAR
return $ret;
}
// }}}
// {{{ getShortcuts()
/**
* Return a list of all the command shortcuts defined by this class.
* @return array shortcut => command
* @access public
*/
function getShortcuts()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
if (isset($this->commands[$command]['shortcut'])) {
$ret[$this->commands[$command]['shortcut']] = $command;
}
}
return $ret;
}
// }}}
// {{{ getOptions()
@ -151,10 +170,34 @@ class PEAR_Command_Common extends PEAR
if (isset($this->commands[$command]['options']) &&
count($this->commands[$command]['options']))
{
$help = "Accepted options:\n";
// XXX Add long options
$help = "Options:\n";
foreach ($this->commands[$command]['options'] as $k => $v) {
$help .= " -" . $v['shortopt'] . " " . $v['doc'] . "\n";
if (isset($v['shortopt'])) {
$s = $v['shortopt'];
if (@$s{1} == ':') {
$argname = '';
$optional = false;
if (@$s{2} == ':') {
$optional = true;
$argname = substr($s, 3);
} else {
$argname = substr($s, 2);
}
if (empty($argname)) {
$argname = 'arg';
}
if ($optional) {
$help .= " -$s [$argname], --{$k}[=$argname]\n";
} else {
$help .= " -$s $argname, --$k=$argname\n";
}
} else {
$help .= " -$s, --$k\n";
}
} else {
$help .= " --$k\n";
}
$help .= " $v[doc]\n";
}
return $help;
}
@ -168,7 +211,17 @@ class PEAR_Command_Common extends PEAR
{
$func = @$this->commands[$command]['function'];
if (empty($func)) {
return $this->raiseError("unknown command `$command'");
// 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)) {
return $this->raiseError("unknown command `$command'");
}
break;
}
}
}
return $this->$func($command, $options, $params);
}

View File

@ -32,14 +32,18 @@ class PEAR_Command_Config extends PEAR_Command_Common
var $commands = array(
'config-show' => array(
'summary' => 'Show All Settings',
'function' => 'doConfigShow',
'shortcut' => 'csh',
'options' => array(),
'doc' => 'Displays all configuration values. An optional argument
'doc' => '
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".
',
),
'config-get' => array(
'summary' => 'Show One Setting',
'function' => 'doConfigGet',
'options' => array(),
'doc' => 'Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
@ -51,6 +55,7 @@ just specified.
),
'config-set' => array(
'summary' => 'Change Setting',
'function' => 'doConfigSet',
'options' => array(),
'doc' => 'Sets the value of one configuration parameter. The first
argument is the name of the parameter, the second argument is the new value.
@ -72,74 +77,75 @@ in. The default layer is "user".
parent::PEAR_Command_Common($ui, $config);
}
function run($command, $options, $params)
function doConfigShow($command, $options, $params)
{
$cf = &$this->config;
// $params[0] -> the layer
if ($error = $this->_checkLayer(@$params[0])) {
$failmsg .= $error;
break;
}
$keys = $this->config->getKeys();
sort($keys);
$this->ui->startTable(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) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
$this->ui->tableRow(array($key, $value));
}
$this->ui->endTable();
return true;
}
function doConfigGet($command, $options, $params)
{
// $params[0] -> the parameter
// $params[1] -> the layer
if ($error = $this->_checkLayer(@$params[1])) {
$failmsg .= $error;
break;
}
if (sizeof($params) < 1 || sizeof($params) > 2) {
$failmsg .= "config-get expects 1 or 2 parameters";
} elseif (sizeof($params) == 1) {
$this->ui->displayLine("$params[0] = " . $this->config->get($params[0]));
} else {
$this->ui->displayLine("($params[1])$params[0] = " .
$this->config->get($params[0], $params[1]));
}
return true;
}
function doConfigSet($command, $options, $params)
{
// $param[0] -> a parameter to set
// $param[1] -> the value for the parameter
// $param[2] -> the layer
$failmsg = '';
switch ($command) {
case 'config-show': {
// $params[0] -> the layer
if ($error = $this->_checkLayer(@$params[0])) {
$failmsg .= $error;
break;
}
$keys = $cf->getKeys();
sort($keys);
$this->ui->startTable(array('caption' => 'Configuration:'));
foreach ($keys as $key) {
$type = $cf->getType($key);
$value = $cf->get($key, @$params[0]);
if ($type == 'password' && $value) {
$value = '********';
}
if (empty($value)) {
$value = '<not set>';
}
$this->ui->tableRow(array($key, $value));
}
$this->ui->endTable();
break;
}
case 'config-get': {
// $params[0] -> the parameter
// $params[1] -> the layer
if ($error = $this->_checkLayer(@$params[1])) {
$failmsg .= $error;
break;
}
if (sizeof($params) < 1 || sizeof($params) > 2) {
$failmsg .= "config-get expects 1 or 2 parameters. Try \"help config-get\" for help";
} elseif (sizeof($params) == 1) {
$this->ui->displayLine("$params[0] = " . $cf->get($params[0]));
} else {
$this->ui->displayLine("($params[1])$params[0] = " .
$cf->get($params[0], $params[1]));
}
break;
}
case 'config-set': {
// $param[0] -> a parameter to set
// $param[1] -> the value for the parameter
// $param[2] -> the layer
if (sizeof($params) < 2 || sizeof($params) > 3) {
$failmsg .= "config-set expects 2 or 3 parameters. Try \"help config-set\" for help";
break;
}
if ($error = $this->_checkLayer(@$params[2])) {
$failmsg .= $error;
break;
}
if (!call_user_func_array(array(&$cf, 'set'), $params))
{
$failmsg = "config-set (" . implode(", ", $params) . ") failed";
} else {
$cf->store();
}
break;
}
default: {
return false;
}
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 (!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);

View File

@ -57,7 +57,8 @@ class PEAR_Command_Install extends PEAR_Command_Common
'doc' => 'request uncompressed files when downloading',
),
),
'doc' => 'Installs one or more PEAR packages. You can specify a package to
'doc' => '<package> ...
Installs one or more PEAR packages. You can specify a package to
install in four ways:
"Package-1.0.tgz" : installs from a local file
@ -97,7 +98,8 @@ four ways of specifying packages.
'doc' => 'request uncompressed files when downloading',
),
),
'doc' => 'Upgrades one or more PEAR packages. See documentation for the
'doc' => '<package> ...
Upgrades one or more PEAR packages. See documentation for the
"install" command for ways to specify a package.
When upgrading, your package will be updated if the provided new
@ -119,14 +121,9 @@ More than one package may be specified at once.
'doc' => 'do not remove files, only register the packages as not installed',
),
),
'doc' => 'Upgrades one or more PEAR packages. See documentation for the
"install" 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' => '<package> ...
Uninstalls one or more PEAR packages. More than one package may be
specified at once.
'),
);
@ -145,52 +142,46 @@ More than one package may be specified at once.
}
// }}}
// {{{ run()
function run($command, $options, $params)
function doInstall($command, $options, $params)
{
$this->installer = &new PEAR_Installer($ui);
// return parent::run($command, $options, $params);
$failmsg = '';
switch ($command) {
case 'upgrade':
$options['upgrade'] = true;
// fall through
case 'install':
foreach ($params as $pkg) {
$bn = basename($pkg);
$info = $this->installer->install($pkg, $options, $this->config);
if (is_array($info)) {
if ($this->config->get('verbose') > 0) {
$label = "$info[package] $info[version]";
$this->ui->displayLine("$command ok: $label");
}
} else {
$failmsg = "$command failed";
}
}
break;
case 'uninstall':
foreach ($params as $pkg) {
if ($this->installer->uninstall($pkg, $options)) {
if ($this->config->get('verbose') > 0) {
$this->ui->displayLine("uninstall ok");
}
} else {
$failmsg = "uninstall failed";
}
}
break;
default:
return false;
if (empty($this->installer)) {
$this->installer = &new PEAR_Installer($ui);
}
if ($failmsg) {
return $this->raiseError($failmsg);
if ($command == 'upgrade') {
$options[$command] = true;
}
foreach ($params as $pkg) {
$bn = basename($pkg);
$info = $this->installer->install($pkg, $options, $this->config);
if (is_array($info)) {
if ($this->config->get('verbose') > 0) {
$label = "$info[package] $info[version]";
$this->ui->displayLine("$command ok: $label");
}
} else {
return $this->raiseError("$command failed");
}
}
}
function doUninstall($command, $options, $params)
{
if (empty($this->installer)) {
$this->installer = &new PEAR_Installer($ui);
}
foreach ($params as $pkg) {
if ($this->installer->uninstall($pkg, $options)) {
if ($this->config->get('verbose') > 0) {
$this->ui->displayLine("uninstall ok");
}
} else {
return $this->raiseError("uninstall failed");
}
}
return true;
}
// }}}
}
?>

View File

@ -37,32 +37,40 @@ class PEAR_Command_Package extends PEAR_Command_Common
'doc' => 'Print the name of the packaged file.',
),
),
'doc' => 'Creates a PEAR package from its description file (usually
called package.xml).
'doc' => '[descfile]
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.
'doc' => '
Extracts information from a package file and displays it.
',
),
'package-list' => array(
'summary' => 'List Files in Package',
'function' => 'doPackageList',
'shortcut' => 'pl',
'options' => array(),
'doc' => '',
'doc' => '
',
),
'package-validate' => array(
'summary' => 'Validate Package Consistency',
'function' => 'doPackageValidate',
'shortcut' => 'pv',
'options' => array(),
'doc' => '',
'doc' => '
',
),
'cvstag' => array(
'summary' => 'Set CVS Release Tag',
'function' => 'doCvsTag',
'shortcut' => 'ct',
'options' => array(
'quiet' => array(
'shortopt' => 'q',
@ -74,20 +82,28 @@ called package.xml).
),
'slide' => array(
'shortopt' => 'F',
'doc' => 'Move tag if it exists',
'doc' => 'Move (slide) tag if it exists',
),
'delete' => array(
'shortopt' => 'd',
'doc' => 'Remote tag',
'doc' => 'Remove tag',
),
),
'doc' => '',
'doc' => '
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.
',
),
'run-tests' => array(
'summary' => 'Run Regression Tests',
'function' => 'doRunTests',
'shortcut' => 'rt',
'options' => array(),
'doc' => '',
'doc' => '[testfile|dir ...]
Run regression tests with PHP\'s regression testing script (run-tests.php).',
),
);

View File

@ -26,18 +26,23 @@ require_once 'PEAR/Config.php';
class PEAR_Command_Registry extends PEAR_Command_Common
{
var $commands = array(
'list-installed' => array(
'list' => array(
'summary' => 'List Installed Packages',
'function' => 'doListInstalled',
'function' => 'doList',
'options' => array(),
'doc' => 'List the PEAR packages installed in your php_dir ({config php_dir)).
'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.
',
),
'shell-test' => array(
'summary' => 'Shell Script Test',
'shortcut' => 'stest',
'function' => 'doShellTest',
'options' => array(),
'doc' => 'Tests if a package is installed in the system. Will exit(1) if it is not.
'doc' => '<package> [[relation] version]
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
@ -54,28 +59,84 @@ class PEAR_Command_Registry extends PEAR_Command_Common
parent::PEAR_Command_Common($ui, $config);
}
function doListInstalled($command, $options, $params)
function doList($command, $options, $params)
{
$reg = new PEAR_Registry($this->config->get('php_dir'));
$installed = $reg->packageInfo();
$i = $j = 0;
$this->ui->startTable(
array('caption' => 'Installed packages:',
'border' => true));
foreach ($installed as $package) {
if ($i++ % 20 == 0) {
$this->ui->tableRow(
array('Package', 'Version', 'State'),
array('bold' => true));
if (sizeof($params) == 0) {
$installed = $reg->packageInfo();
$i = $j = 0;
$this->ui->startTable(
array('caption' => 'Installed packages:',
'border' => true));
foreach ($installed as $package) {
if ($i++ % 20 == 0) {
$this->ui->tableRow(
array('Package', 'Version', 'State'),
array('bold' => true));
}
$this->ui->tableRow(array($package['package'],
$package['version'],
@$package['release_state']));
}
$this->ui->tableRow(array($package['package'],
$package['version'],
@$package['release_state']));
if ($i == 0) {
$this->ui->tableRow(array('(no packages installed)'));
}
$this->ui->endTable();
} 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;
} else {
$info = $reg->packageInfo($params[0]);
$headings = array('Type', 'Install Path');
$installed = true;
}
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
$list =$info['filelist'];
$caption = 'Contents of ' . basename($params[0]);
$this->ui->startTable(array('caption' => $caption,
'border' => true));
$this->ui->tableRow($headings, array('bold' => true));
foreach ($list as $file => $att) {
if (isset($att['baseinstalldir'])) {
$dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
$file;
} else {
$dest = $file;
}
switch ($att['role']) {
case 'test':
$dest = '-- will not be installed --'; break;
case 'doc':
$dest = $this->config->get('doc_dir') . DIRECTORY_SEPARATOR .
$dest;
break;
case 'php':
default:
$dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
$dest;
}
$dest = preg_replace('!/+!', '/', $dest);
$file = preg_replace('!/+!', '/', $file);
$opts = array(0 => array('wrap' => 23),
1 => array('wrap' => 45)
);
if ($installed) {
$this->ui->tableRow(array($att['role'], $dest), null, $opts);
} else {
$this->ui->tableRow(array($file, $dest), null, $opts);
}
}
$this->ui->endTable();
}
if ($i == 0) {
$this->ui->tableRow(array('(no packages installed yet)'));
}
$this->ui->endTable();
return true;
}

View File

@ -28,25 +28,42 @@ class PEAR_Command_Remote extends PEAR_Command_Common
// {{{ command definitions
var $commands = array(
'remote-package-info' => array(
'info-remote' => array(
'summary' => 'Information About Remote Packages',
'function' => 'doRemotePackageInfo',
'function' => 'doInfoRemote',
'options' => array(),
'doc' => '<package>
Get details on a package from the server.',
),
'list-upgrades' => array(
'summary' => 'List Available Upgrades',
'function' => 'doListUpgrades',
'options' => array(),
'doc' => '
List releases on the server of packages you have installed where
a newer version is available with the same release state (stable etc.).'
),
'list-remote-packages' => array(
'list-remote' => array(
'summary' => 'List Remote Packages',
'function' => 'doListRemotePackages',
'function' => 'doListRemote',
'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',
'options' => array(),
'options' => array(
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'download an uncompressed (.tar) file',
),
),
'doc' => '{package|package-version}
Download a package tarball. The file 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.',
),
);
@ -65,16 +82,17 @@ class PEAR_Command_Remote extends PEAR_Command_Common
// }}}
// {{{ remote-package-info
// {{{ info-remote
function doRemotePackageInfo($command, $options, $params)
function doInfoRemote($command, $options, $params)
{
return false; // coming soon
}
// }}}
// {{{ list-remote-packages
// {{{ list-remote
function doListRemotePackages($command, $options, $params)
function doListRemote($command, $options, $params)
{
$r = new PEAR_Remote($this->config);
$available = $r->call('package.listAll', true);

View File

@ -129,13 +129,15 @@ if (empty($command) && ($store_user_config || $store_system_config)) {
if ($fetype == 'Gtk') {
Gtk::main();
} else do {
if (empty($all_commands[$command]) || $command == 'help') {
if ($command == 'help') {
usage(null, @$options[1][0]);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$cmd = PEAR_Command::factory($command, $config);
PEAR::popErrorHandling();
if (PEAR::isError($cmd)) {
die($cmd->getMessage());
usage(null, @$options[1][0]);
}
$short_args = $long_args = null;
@ -175,7 +177,6 @@ function usage($error = null, $helpsubject = null)
{
global $progname, $all_commands;
$stderr = fopen('php://stderr', 'w');
fputs($stderr, "\n");
if (PEAR::isError($error)) {
fputs($stderr, $error->getMessage() . "\n");
} elseif ($error !== null) {
@ -217,11 +218,18 @@ function cmdHelp($command)
" -S store system configuration\n".
" -u foo unset `foo' in the user configuration\n".
" -h, -? display help/usage (this message)\n";
} elseif ($command == "shortcuts") {
$sc = PEAR_Command::getShortcuts();
$ret = "Shortcuts:\n";
foreach ($sc as $s => $c) {
$ret .= sprintf(" %-8s %s\n", $s, $c);
}
return $ret;
} elseif ($help = PEAR_Command::getHelp($command)) {
if (is_string($help)) {
return "$help\n";
return "pear $command [options] $help\n";
}
return "{$help[0]}\n{$help[1]}";
return "pear $command [options] $help[0]\n$help[1]";
}
return "No such command";
}