From 9752cbde1201f3e7b74dc67310cc5cd840a17443 Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Mon, 28 Mar 2005 16:38:59 +0000 Subject: merge in PEAR 1.3.5 --- pear/OS/Guess.php | 25 +++- pear/PEAR.php | 98 +++++++++++++-- pear/PEAR/Builder.php | 101 ++++++++------- pear/PEAR/Command/Install.php | 6 + pear/PEAR/Command/Package.php | 160 +++++++++++++++++++----- pear/PEAR/Common.php | 78 ++++++++++-- pear/PEAR/Dependency.php | 7 +- pear/PEAR/Downloader.php | 12 +- pear/PEAR/ErrorStack.php | 123 ++++++++++--------- pear/PEAR/Exception.php | 251 +++++++++++++++++++++++++++++--------- pear/PEAR/Installer.php | 36 +++--- pear/PEAR/Registry.php | 7 +- pear/package-PEAR.xml | 120 +++++++++++------- pear/package.dtd | 8 +- pear/scripts/pearcmd.php | 15 ++- pear/template.spec | 20 +-- pear/tests/pear_config.phpt | 1 - pear/tests/pear_config_1.1.phpt | 2 - pear/tests/pear_registry_1.1.phpt | 4 - 19 files changed, 773 insertions(+), 301 deletions(-) (limited to 'pear') diff --git a/pear/OS/Guess.php b/pear/OS/Guess.php index 4b366d8c2a..8b9b0606a9 100644 --- a/pear/OS/Guess.php +++ b/pear/OS/Guess.php @@ -68,6 +68,11 @@ // SparcStation 20 Solaris 8: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 // +// Mac OS X (Darwin) +// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh +// +// Mac OS X early versions +// // }}} @@ -97,11 +102,11 @@ class OS_Guess static $sysmap = array( 'HP-UX' => 'hpux', 'IRIX64' => 'irix', - // Darwin? ); static $cpumap = array( 'i586' => 'i386', 'i686' => 'i386', + 'ppc' => 'powerpc', ); if ($uname === null) { $uname = php_uname(); @@ -138,6 +143,24 @@ class OS_Guess // use only the first two digits from the kernel version $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); break; + case 'Mac' : + $sysname = 'darwin'; + $nodename = $parts[2]; + $release = $parts[3]; + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + break; + case 'Darwin' : + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; default: $release = ereg_replace('-.*', '', $parts[2]); break; diff --git a/pear/PEAR.php b/pear/PEAR.php index a42b825f6a..fa89ea56d4 100644 --- a/pear/PEAR.php +++ b/pear/PEAR.php @@ -59,7 +59,7 @@ $GLOBALS['_PEAR_destructor_object_list'] = array(); $GLOBALS['_PEAR_shutdown_funcs'] = array(); $GLOBALS['_PEAR_error_handler_stack'] = array(); -ini_set('track_errors', true); +@ini_set('track_errors', true); /** * Base class for other PEAR classes. Provides rudimentary @@ -152,7 +152,7 @@ class PEAR */ function PEAR($error_class = null) { - $classname = get_class($this); + $classname = strtolower(get_class($this)); if ($this->_debug) { print "PEAR constructor called, class=$classname\n"; } @@ -164,6 +164,10 @@ class PEAR if (method_exists($this, $destructor)) { global $_PEAR_destructor_object_list; $_PEAR_destructor_object_list[] = &$this; + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } break; } else { $classname = get_parent_class($classname); @@ -187,7 +191,7 @@ class PEAR */ function _PEAR() { if ($this->_debug) { - printf("PEAR destructor called, class=%s\n", get_class($this)); + printf("PEAR destructor called, class=%s\n", strtolower(get_class($this))); } } @@ -561,6 +565,77 @@ class PEAR } // }}} + function staticPushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + $stack[] = array($def_mode, $def_options); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $def_mode = $mode; + $def_options = $options; + break; + + case PEAR_ERROR_CALLBACK: + $def_mode = $mode; + // class/object method callback + if (is_callable($options)) { + $def_options = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + $stack[] = array($mode, $options); + return true; + } + + function staticPopErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + return true; + } + // {{{ pushErrorHandling() /** @@ -665,6 +740,9 @@ function _PEAR_call_destructors() sizeof($_PEAR_destructor_object_list)) { reset($_PEAR_destructor_object_list); + if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); + } while (list($k, $objref) = each($_PEAR_destructor_object_list)) { $classname = get_class($objref); while ($classname) { @@ -738,7 +816,9 @@ class PEAR_Error $this->mode = $mode; $this->userinfo = $userinfo; if (function_exists("debug_backtrace")) { - $this->backtrace = debug_backtrace(); + if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + } } if ($mode & PEAR_ERROR_CALLBACK) { $this->level = E_USER_NOTICE; @@ -929,14 +1009,16 @@ class PEAR_Error E_USER_ERROR => 'error'); if ($this->mode & PEAR_ERROR_CALLBACK) { if (is_array($this->callback)) { - $callback = get_class($this->callback[0]) . '::' . + $callback = (is_object($this->callback[0]) ? + strtolower(get_class($this->callback[0])) : + $this->callback[0]) . '::' . $this->callback[1]; } else { $callback = $this->callback; } return sprintf('[%s: message="%s" code=%d mode=callback '. 'callback=%s prefix="%s" info="%s"]', - get_class($this), $this->message, $this->code, + strtolower(get_class($this)), $this->message, $this->code, $callback, $this->error_message_prefix, $this->userinfo); } @@ -954,7 +1036,7 @@ class PEAR_Error } return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. 'prefix="%s" info="%s"]', - get_class($this), $this->message, $this->code, + strtolower(get_class($this)), $this->message, $this->code, implode("|", $modes), $levels[$this->level], $this->error_message_prefix, $this->userinfo); @@ -963,8 +1045,6 @@ class PEAR_Error // }}} } -register_shutdown_function("_PEAR_call_destructors"); - /* * Local Variables: * mode: php diff --git a/pear/PEAR/Builder.php b/pear/PEAR/Builder.php index f7a7f4ea8c..0f37d24acb 100644 --- a/pear/PEAR/Builder.php +++ b/pear/PEAR/Builder.php @@ -150,41 +150,50 @@ class PEAR_Builder extends PEAR_Common } // }}} - // {{{ build() + // {{{ _harventInstDir + /** + * @param string + * @param string + * @param array + * @access private + */ + function _harvestInstDir($dest_prefix, $dirname, &$built_files) + { + $d = opendir($dirname); + if (!$d) + return false; + + $ret = true; + while (($ent = readdir($d)) !== false) { + if ($ent{0} == '.') + continue; + + $full = $dirname . DIRECTORY_SEPARATOR . $ent; + if (is_dir($full)) { + if (!$this->_harvestInstDir( + $dest_prefix . DIRECTORY_SEPARATOR . $ent, + $full, $built_files)) { + $ret = false; + break; + } + } else { + $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; + $built_files[] = array( + 'file' => $full, + 'dest' => $dest, + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + } + } + closedir($d); + return $ret; + } - function _harvest_inst_dir($dest_prefix, $dirname, &$built_files) - { - $d = opendir($dirname); - if (!$d) - return false; - - $ret = true; - while (($ent = readdir($d)) !== false) { - if ($ent{0} == '.') - continue; - - $full = $dirname . DIRECTORY_SEPARATOR . $ent; - if (is_dir($full)) { - if (!$this->_harvest_inst_dir( - $dest_prefix . DIRECTORY_SEPARATOR . $ent, - $full, $built_files)) { - $ret = false; - break; - } - } else { - $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; - $built_files[] = array( - 'file' => $full, - 'dest' => $dest, - 'php_api' => $this->php_api_version, - 'zend_mod_api' => $this->zend_module_api_no, - 'zend_ext_api' => $this->zend_extension_api_no, - ); - } - } - closedir($d); - return $ret; - } + // }}} + + // {{{ build() /** * Build an extension from source. Runs "phpize" in the source @@ -232,7 +241,7 @@ class PEAR_Builder extends PEAR_Common $dir = getcwd(); $this->log(2, "building in $dir"); $this->current_callback = $callback; - putenv('PATH=' . getenv('PATH') . ':' . $this->config->get('bin_dir')); + putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); if (PEAR::isError($err)) { return $err; @@ -265,19 +274,18 @@ class PEAR_Builder extends PEAR_Common } $build_basedir = "/var/tmp/pear-build-$user"; $build_dir = "$build_basedir/$info[package]-$info[version]"; - $inst_dir = "$build_basedir/install-$info[package]-$info[version]"; + $inst_dir = "$build_basedir/install-$info[package]-$info[version]"; $this->log(1, "building in $build_dir"); if (is_dir($build_dir)) { - System::rm("-rf $build_dir"); + System::rm(array('-rf', $build_dir)); } - if (!System::mkDir("-p $build_dir")) { + if (!System::mkDir(array('-p', $build_dir))) { return $this->raiseError("could not create build dir: $build_dir"); } - $this->addTempFile($build_dir); - if (!System::mkDir("-p $inst_dir")) { - return $this->raiseError("could not create install dir: $inst_dir"); - } + if (!System::mkDir(array('-p', $inst_dir))) { + return $this->raiseError("could not create temporary install dir: $inst_dir"); + } $this->addTempFile($inst_dir); if (getenv('MAKE')) { @@ -288,11 +296,13 @@ class PEAR_Builder extends PEAR_Common $to_run = array( $configure_command, $make_command, - "$make_command INSTALL_ROOT=$inst_dir install" + "$make_command INSTALL_ROOT=\"$inst_dir\" install", + "find \"$inst_dir\" -ls" ); if (!@chdir($build_dir)) { return $this->raiseError("could not chdir to $build_dir"); } + putenv('PHP_PEAR_VERSION=@PEAR-VER@'); foreach ($to_run as $cmd) { $err = $this->_runCommand($cmd, $callback); if (PEAR::isError($err)) { @@ -309,9 +319,8 @@ class PEAR_Builder extends PEAR_Common return $this->raiseError("no `modules' directory found"); } $built_files = array(); - $prefix = exec("php-config --prefix"); - $this->_harvest_inst_dir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); - print_r($built_files); + $prefix = exec("php-config --prefix"); + $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); chdir($old_cwd); return $built_files; } diff --git a/pear/PEAR/Command/Install.php b/pear/PEAR/Command/Install.php index f804a838e3..7a89c7cddd 100644 --- a/pear/PEAR/Command/Install.php +++ b/pear/PEAR/Command/Install.php @@ -303,7 +303,13 @@ package if needed. $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; + } if (is_array($info)) { if ($this->config->get('verbose') > 0) { $label = "$info[package] $info[version]"; diff --git a/pear/PEAR/Command/Package.php b/pear/PEAR/Command/Package.php index dcdc86bd1a..13f0c920f8 100644 --- a/pear/PEAR/Command/Package.php +++ b/pear/PEAR/Command/Package.php @@ -155,7 +155,21 @@ use the "slide" option to move the release tag. 'summary' => 'Run Regression Tests', 'function' => 'doRunTests', 'shortcut' => 'rt', - 'options' => array(), + '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).', ), @@ -250,6 +264,9 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm { $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(); @@ -264,12 +281,6 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm if (isset($options['showname'])) { $this->output = $result; } - /* (cox) What is supposed to do that code? - $lines = explode("\n", $this->output); - foreach ($lines as $line) { - $this->output .= $line."n"; - } - */ if (PEAR::isError($result)) { $this->output .= "Package failed: ".$result->getMessage(); } @@ -434,34 +445,118 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm function doRunTests($command, $options, $params) { - $cwd = getcwd(); - $php = $this->config->get('php_bin'); - putenv("TEST_PHP_EXECUTABLE=$php"); - // all core PEAR tests use this constant to determine whether they should be run or not - putenv("PHP_PEAR_RUNTESTS=1"); - $ip = ini_get("include_path"); - $ps = OS_WINDOWS ? ';' : ':'; - $run_tests = $rtsts = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . 'run-tests.php'; - if (!file_exists($run_tests)) { - $run_tests = PEAR_INSTALL_DIR . DIRECTORY_SEPARATOR . 'run-tests.php'; - if (!file_exists($run_tests)) { - return $this->raiseError("No run-tests.php file found. Please copy this ". - "file from the sources of your PHP distribution to $rtsts"); + 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; + } } } - if (OS_WINDOWS) { - // note, this requires a slightly modified version of run-tests.php - // for some setups - // unofficial download location is in the pear-dev archives - $argv = $params; - array_unshift($argv, $run_tests); - $argc = count($argv); - include $run_tests; - } else { - $plist = implode(' ', $params); - $cmd = "$php -d include_path=$cwd$ps$ip -f $run_tests -- $plist"; - system($cmd); + $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); + } + } + return true; } @@ -642,6 +737,7 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm if (!isset($attr['role'])) { continue; } + $name = preg_replace('![/:\\\\]!', '/', $name); if ($attr['role'] == 'doc') { $info['doc_files'] .= " $name"; diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php index 2f9c611823..cfb73c6031 100644 --- a/pear/PEAR/Common.php +++ b/pear/PEAR/Common.php @@ -34,7 +34,7 @@ define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/'); // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 -define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-z]+\d*)?'); +define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i'); // XXX far from perfect :-) @@ -69,7 +69,7 @@ $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldli * Valid dependency relations * @var array */ -$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not'); +$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); /** * Valid file roles @@ -98,7 +98,9 @@ $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'p // }}} /** - * Class providing common functionality for PEAR adminsitration classes. + * Class providing common functionality for PEAR administration classes. + * @deprecated This class will disappear, and its components will be spread + * into smaller classes, like the AT&T breakup */ class PEAR_Common extends PEAR { @@ -142,12 +144,6 @@ class PEAR_Common extends PEAR * @access private */ var $_validPackageFile; - /** - * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()} - * @var array - * @access private - */ - var $_packageSortTree; // }}} @@ -1133,18 +1129,31 @@ class PEAR_Common extends PEAR if (!empty($d['optional'])) { if (!in_array($d['optional'], array('yes', 'no'))) { $errors[] = "dependency $i: invalid relation optional attribute '$d[optional]', should be one of: yes no"; + } else { + if (($d['rel'] == 'not' || $d['rel'] == 'ne') && $d['optional'] == 'yes') { + $errors[] = "dependency $i: 'not' and 'ne' dependencies cannot be " . + "optional"; + } } } - if ($d['rel'] != 'has' && empty($d['version'])) { + if ($d['rel'] != 'not' && $d['rel'] != 'has' && empty($d['version'])) { $warnings[] = "dependency $i: missing version"; - } elseif ($d['rel'] == 'has' && !empty($d['version'])) { - $warnings[] = "dependency $i: version ignored for `has' dependencies"; + } elseif (($d['rel'] == 'not' || $d['rel'] == 'has') && !empty($d['version'])) { + $warnings[] = "dependency $i: version ignored for `$d[rel]' dependencies"; + } + if ($d['rel'] == 'not' && !empty($d['version'])) { + $warnings[] = "dependency $i: 'not' defines a total conflict, to exclude " . + "specific versions, use 'ne'"; } if ($d['type'] == 'php' && !empty($d['name'])) { $warnings[] = "dependency $i: name ignored for php type dependencies"; } elseif ($d['type'] != 'php' && empty($d['name'])) { $errors[] = "dependency $i: missing name"; } + if ($d['type'] == 'php' && $d['rel'] == 'not') { + $errors[] = "dependency $i: PHP dependencies cannot use 'not' " . + "rel, use 'ne' to exclude versions"; + } $i++; } } @@ -1293,6 +1302,15 @@ class PEAR_Common extends PEAR if (!function_exists("token_get_all")) { return false; } + if (!defined('T_DOC_COMMENT')) { + define('T_DOC_COMMENT', T_COMMENT); + } + if (!defined('T_INTERFACE')) { + define('T_INTERFACE', -1); + } + if (!defined('T_IMPLEMENTS')) { + define('T_IMPLEMENTS', -1); + } if (!$fp = @fopen($file, "r")) { return false; } @@ -1315,17 +1333,21 @@ class PEAR_Common extends PEAR $brace_level = 0; $lastphpdoc = ''; $current_class = ''; + $current_interface = ''; $current_class_level = -1; $current_function = ''; $current_function_level = -1; $declared_classes = array(); + $declared_interfaces = array(); $declared_functions = array(); $declared_methods = array(); $used_classes = array(); $used_functions = array(); $extends = array(); + $implements = array(); $nodeps = array(); $inquote = false; + $interface = false; for ($i = 0; $i < sizeof($tokens); $i++) { if (is_array($tokens[$i])) { list($token, $data) = $tokens[$i]; @@ -1341,6 +1363,14 @@ class PEAR_Common extends PEAR } } switch ($token) { + case T_WHITESPACE: + continue; + case ';': + if ($interface) { + $current_function = ''; + $current_function_level = -1; + } + break; case '"': $inquote = true; break; @@ -1362,6 +1392,8 @@ class PEAR_Common extends PEAR case ']': $bracket_level--; continue 2; case '(': $paren_level++; continue 2; case ')': $paren_level--; continue 2; + case T_INTERFACE: + $interface = true; case T_CLASS: if (($current_class_level != -1) || ($current_function_level != -1)) { PEAR::raiseError("Parser error: Invalid PHP file $file", @@ -1371,19 +1403,38 @@ class PEAR_Common extends PEAR case T_FUNCTION: case T_NEW: case T_EXTENDS: + case T_IMPLEMENTS: $look_for = $token; continue 2; case T_STRING: + if (version_compare(zend_version(), '2.0', '<')) { + if (in_array(strtolower($data), + array('public', 'private', 'protected', 'abstract', + 'interface', 'implements', 'clone', 'throw') + )) { + PEAR::raiseError('Error: PHP5 packages must be packaged by php 5 PEAR'); + return false; + } + } if ($look_for == T_CLASS) { $current_class = $data; $current_class_level = $brace_level; $declared_classes[] = $current_class; + } elseif ($look_for == T_INTERFACE) { + $current_interface = $data; + $current_class_level = $brace_level; + $declared_interfaces[] = $current_interface; + } elseif ($look_for == T_IMPLEMENTS) { + $implements[$current_class] = $data; } elseif ($look_for == T_EXTENDS) { $extends[$current_class] = $data; } elseif ($look_for == T_FUNCTION) { if ($current_class) { $current_function = "$current_class::$data"; $declared_methods[$current_class][] = $data; + } elseif ($current_interface) { + $current_function = "$current_interface::$data"; + $declared_methods[$current_interface][] = $data; } else { $current_function = $data; $declared_functions[] = $current_function; @@ -1398,6 +1449,7 @@ class PEAR_Common extends PEAR case T_VARIABLE: $look_for = 0; continue 2; + case T_DOC_COMMENT: case T_COMMENT: if (preg_match('!^/\*\*\s!', $data)) { $lastphpdoc = $data; @@ -1422,10 +1474,12 @@ class PEAR_Common extends PEAR return array( "source_file" => $file, "declared_classes" => $declared_classes, + "declared_interfaces" => $declared_interfaces, "declared_methods" => $declared_methods, "declared_functions" => $declared_functions, "used_classes" => array_diff(array_keys($used_classes), $nodeps), "inheritance" => $extends, + "implements" => $implements, ); } diff --git a/pear/PEAR/Dependency.php b/pear/PEAR/Dependency.php index 3239fc98ee..ec2bd7e86d 100644 --- a/pear/PEAR/Dependency.php +++ b/pear/PEAR/Dependency.php @@ -204,7 +204,7 @@ class PEAR_Dependency } foreach ($deps as $dep) { if ($dep['type'] == 'pkg' && strcasecmp($dep['name'], $package) == 0) { - if ($dep['rel'] == 'ne') { + if ($dep['rel'] == 'ne' || $dep['rel'] == 'not') { continue; } if (isset($dep['optional']) && $dep['optional'] == 'yes') { @@ -244,7 +244,7 @@ class PEAR_Dependency } if (!extension_loaded($name)) { - if ($relation == 'ne') { + if ($relation == 'not') { return false; } if ($opt) { @@ -322,7 +322,8 @@ class PEAR_Dependency return false; } if ($relation == 'not') { - $errmsg = "Invalid dependency - 'not' is allowed when specifying PHP, you must run PHP in PHP"; + $errmsg = 'Invalid dependency - "not" is not allowed for php dependencies, ' . + 'php cannot conflict with itself'; return PEAR_DEPENDENCY_BAD_DEPENDENCY; } if (substr($req, 0, 2) == 'v.') { diff --git a/pear/PEAR/Downloader.php b/pear/PEAR/Downloader.php index 17ad4566a1..793cc0410e 100644 --- a/pear/PEAR/Downloader.php +++ b/pear/PEAR/Downloader.php @@ -381,7 +381,8 @@ class PEAR_Downloader extends PEAR_Common // there are no dependencies continue; } - foreach($alldeps as $info) { + $fail = false; + foreach ($alldeps as $info) { if ($info['type'] != 'pkg') { continue; } @@ -389,11 +390,18 @@ class PEAR_Downloader extends PEAR_Common if ($ret === false) { continue; } + if ($ret === 0) { + $fail = true; + continue; + } if (PEAR::isError($ret)) { return $ret; } $deppackages[] = $ret; } // foreach($alldeps + if ($fail) { + $deppackages = array(); + } } if (count($deppackages)) { @@ -561,7 +569,7 @@ class PEAR_Downloader extends PEAR_Common $savestate = array_shift($get); $this->pushError( "Release for '$package' dependency '$info[name]' " . "has state '$savestate', requires '$state'"); - return false; + return 0; } if (in_array(strtolower($info['name']), $this->_toDownload) || isset($mywillinstall[strtolower($info['name'])])) { diff --git a/pear/PEAR/ErrorStack.php b/pear/PEAR/ErrorStack.php index 6f44f4d686..d1dcf9233e 100644 --- a/pear/PEAR/ErrorStack.php +++ b/pear/PEAR/ErrorStack.php @@ -35,8 +35,11 @@ * * Since version 0.3alpha, it is possible to specify the exception class * returned from {@link push()} + * + * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can + * still be done quite handily in an error callback or by manipulating the returned array * @author Greg Beaver - * @version 0.6alpha + * @version PEAR1.3.2 (beta) * @package PEAR_ErrorStack * @category Debugging * @license http://www.php.net/license/3_0.txt PHP License v3.0 @@ -119,6 +122,10 @@ define('PEAR_ERRORSTACK_LOG', 3); * If this is returned, then the error is completely ignored. */ define('PEAR_ERRORSTACK_IGNORE', 4); +/** + * If this is returned, then the error is logged and die() is called. + */ +define('PEAR_ERRORSTACK_DIE', 5); /**#@-*/ /** @@ -220,13 +227,6 @@ class PEAR_ErrorStack { */ var $_logger = false; - /** - * Class name to use for a PHP 5 exception that will be returned - * @var string - * @access protected - */ - var $_exceptionClass = 'Exception'; - /** * Error messages - designed to be overridden * @var array @@ -242,20 +242,14 @@ class PEAR_ErrorStack { * @param callback $contextCallback callback used for context generation, * defaults to {@link getFileLine()} * @param boolean $throwPEAR_Error - * @param string $exceptionClass exception class to instantiate if - * in PHP 5 */ function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false, - $throwPEAR_Error = false, $exceptionClass = null) + $throwPEAR_Error = false) { $this->_package = $package; $this->setMessageCallback($msgCallback); $this->setContextCallback($contextCallback); $this->_compat = $throwPEAR_Error; - // this allows child classes to simply redefine $this->_exceptionClass - if (!is_null($exceptionClass)) { - $this->_exceptionClass = $exceptionClass; - } } /** @@ -268,29 +262,27 @@ class PEAR_ErrorStack { * @param callback $contextCallback callback used for context generation, * defaults to {@link getFileLine()} * @param boolean $throwPEAR_Error - * @param string $exceptionClass exception class to instantiate if - * in PHP 5 * @param string $stackClass class to instantiate * @static * @return PEAR_ErrorStack */ function &singleton($package, $msgCallback = false, $contextCallback = false, - $throwPEAR_Error = false, $exceptionClass = null, - $stackClass = 'PEAR_ErrorStack') + $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack') { if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; } if (!class_exists($stackClass)) { - $trace = debug_backtrace(); + if (function_exists('debug_backtrace')) { + $trace = debug_backtrace(); + } PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, 'exception', array('stackclass' => $stackClass), 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', false, $trace); } return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = - &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error, - $exceptionClass); + &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); } /** @@ -320,7 +312,11 @@ class PEAR_ErrorStack { */ function setDefaultLogger(&$log) { - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + if (is_object($log) && method_exists($log, 'log') ) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } elseif (is_callable($log)) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } } /** @@ -329,7 +325,11 @@ class PEAR_ErrorStack { */ function setLogger(&$log) { - $this->_logger = &$log; + if (is_object($log) && method_exists($log, 'log') ) { + $this->_logger = &$log; + } elseif (is_callable($log)) { + $this->_logger = &$log; + } } /** @@ -381,14 +381,18 @@ class PEAR_ErrorStack { } /** - * Set an error code => error message mapping callback + * Set a callback that generates context information (location of error) for an error stack * - * This method sets the callback that can be used to generate error - * messages for any PEAR_ErrorStack instance - * @param array|string Callback function/method + * This method sets the callback that can be used to generate context + * information for an error. Passing in NULL will disable context generation + * and remove the expensive call to debug_backtrace() + * @param array|string|null Callback function/method */ function setContextCallback($contextCallback) { + if ($contextCallback === null) { + return $this->_contextCallback = false; + } if (!$contextCallback) { $this->_contextCallback = array(&$this, 'getFileLine'); } else { @@ -454,10 +458,11 @@ class PEAR_ErrorStack { */ function staticPopCallback() { - array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); + $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); } + return $ret; } /** @@ -504,7 +509,7 @@ class PEAR_ErrorStack { * 'time' => time(), * 'context' => $context, * 'message' => $msg, - * //['repackage' => $err] repackaged error array + * //['repackage' => $err] repackaged error array/Exception class * ); * */ @@ -538,13 +543,13 @@ class PEAR_ErrorStack { $msg = call_user_func_array($this->_msgCallback, array(&$this, $err)); $err['message'] = $msg; - } - + } if ($repackage) { $err['repackage'] = $repackage; } $push = $log = true; + $die = false; // try the overriding callback first $callback = $this->staticPopCallback(); if ($callback) { @@ -573,6 +578,9 @@ class PEAR_ErrorStack { case PEAR_ERRORSTACK_LOG: $push = false; break; + case PEAR_ERRORSTACK_DIE: + $die = true; + break; // anything else returned has the same effect as pushandlog } } @@ -585,18 +593,12 @@ class PEAR_ErrorStack { $this->_log($err); } } + if ($die) { + die(); + } if ($this->_compat && $push) { return $this->raiseError($msg, $code, null, null, $err); } - if (class_exists($this->_exceptionClass)) { - $exception = $this->_exceptionClass; - if (is_string($msg) && is_numeric($code)) { - $code = $code + 0; - } - $ret = new $exception($msg, $code); - $ret->errorData = $err; - return $ret; - } return $err; } @@ -630,7 +632,9 @@ class PEAR_ErrorStack { $s = &PEAR_ErrorStack::singleton($package); if ($s->_contextCallback) { if (!$backtrace) { - $backtrace = debug_backtrace(); + if (function_exists('debug_backtrace')) { + $backtrace = debug_backtrace(); + } } } return $s->push($code, $level, $params, $msg, $repackage, $backtrace); @@ -642,7 +646,15 @@ class PEAR_ErrorStack { * @param array $levels Error level => Log constant map * @access protected */ - function _log($err, $levels = array( + function _log($err) + { + if ($this->_logger) { + $logger = &$this->_logger; + } else { + $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; + } + if (is_a($logger, 'Log')) { + $levels = array( 'exception' => PEAR_LOG_CRIT, 'alert' => PEAR_LOG_ALERT, 'critical' => PEAR_LOG_CRIT, @@ -650,17 +662,15 @@ class PEAR_ErrorStack { 'warning' => PEAR_LOG_WARNING, 'notice' => PEAR_LOG_NOTICE, 'info' => PEAR_LOG_INFO, - 'debug' => PEAR_LOG_DEBUG)) - { - if (isset($levels[$err['level']])) { - $level = $levels[$err['level']]; - } else { - $level = PEAR_LOG_INFO; - } - if ($this->_logger) { - $this->_logger->log($err['message'], $level, $err); - } else { - $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']->log($err['message'], $level, $err); + 'debug' => PEAR_LOG_DEBUG); + if (isset($levels[$err['level']])) { + $level = $levels[$err['level']]; + } else { + $level = PEAR_LOG_INFO; + } + $logger->log($err['message'], $level, $err); + } else { // support non-standard logs + call_user_func($logger, $err); } } @@ -757,7 +767,7 @@ class PEAR_ErrorStack { /** * Get a list of all errors since last purge, organized by package * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be - * @param boolean $clearStack Set to purge the error stack of existing errors + * @param boolean $purge Set to purge the error stack of existing errors * @param string $level Set to a level name in order to retrieve only errors of a particular level * @param boolean $merge Set to return a flat array, not organized by package * @param array $sortfunc Function used to sort a merged array - default @@ -765,7 +775,8 @@ class PEAR_ErrorStack { * @static * @return array */ - function staticGetErrors($purge = false, $level = false, $merge = false, $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) + function staticGetErrors($purge = false, $level = false, $merge = false, + $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) { $ret = array(); if (!is_callable($sortfunc)) { diff --git a/pear/PEAR/Exception.php b/pear/PEAR/Exception.php index 8322fd034a..1e191f84ea 100644 --- a/pear/PEAR/Exception.php +++ b/pear/PEAR/Exception.php @@ -15,24 +15,29 @@ // +----------------------------------------------------------------------+ // | Authors: Tomas V.V.Cox | // | Hans Lellelid | -// | | +// | Bertrand Mansion | +// | Greg Beaver | // +----------------------------------------------------------------------+ // // $Id$ -define('PEAR_OBSERVER_PRINT', -2); -define('PEAR_OBSERVER_TRIGGER', -4); -define('PEAR_OBSERVER_DIE', -8); /** * Base PEAR_Exception Class * + * WARNING: This code should be considered stable, but the API is + * subject to immediate and drastic change, so API stability is + * at best alpha + * * 1) Features: * * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) * - Definable triggers, shot when exceptions occur * - Pretty and informative error messages - * - Added more context info avaible (like class, method or cause) + * - Added more context info available (like class, method or cause) + * - cause can be a PEAR_Exception or an array of mixed + * PEAR_Exceptions/PEAR_ErrorStack warnings + * - callbacks for specific exception classes and their children * * 2) Ideas: * @@ -54,8 +59,8 @@ define('PEAR_OBSERVER_DIE', -8); * getCode * getFile * getLine - * getTrace - * getTraceAsString + * getTraceSafe + * getTraceSafeAsString * __toString * * 5) Usage example @@ -88,16 +93,18 @@ define('PEAR_OBSERVER_DIE', -8); * @version $Revision$ * @author Tomas V.V.Cox * @author Hans Lellelid + * @author Bertrand Mansion * */ class PEAR_Exception extends Exception { + const OBSERVER_PRINT = -2; + const OBSERVER_TRIGGER = -4; + const OBSERVER_DIE = -8; protected $cause; - protected $error_class; - protected $error_method; - - private $_method; private static $_observers = array(); + private static $_uniqueid = 0; + private $_trace; /** * Supported signatures: @@ -105,49 +112,56 @@ class PEAR_Exception extends Exception * PEAR_Exception(string $message, int $code); * PEAR_Exception(string $message, Exception $cause); * PEAR_Exception(string $message, Exception $cause, int $code); + * PEAR_Exception(string $message, array $causes); + * PEAR_Exception(string $message, array $causes, int $code); */ public function __construct($message, $p2 = null, $p3 = null) { - $code = null; - $cause = null; - if (is_int($p3) && $p2 instanceof Exception) { - $code = $p3; - $cause = $p2; - } elseif (is_int($p2)) { + if (is_int($p2)) { $code = $p2; - } elseif ($p2 instanceof Exception) { - $cause = $p2; + $this->cause = null; + } elseif ($p2 instanceof Exception || is_array($p2)) { + $code = $p3; + if (is_array($p2) && isset($p2['message'])) { + // fix potential problem of passing in a single warning + $p2 = array($p2); + } + $this->cause = $p2; + } else { + $code = null; + $this->cause = null; } - $this->cause = $cause; - $trace = parent::getTrace(); - $this->error_class = $trace[0]['class']; - $this->error_method = $trace[0]['function']; - $this->_method = $this->error_class . '::' . $this->error_method . '()'; parent::__construct($message, $code); - - $this->_signal(); + $this->signal(); } /** * @param mixed $callback - A valid php callback, see php func is_callable() - * - A PEAR_OBSERVER_* constant - * - An array(const PEAR_OBSERVER_*, mixed $options) - * - * @param string $label - The name of the observer. Use this if you want - * to remove it later with delObserver() + * - A PEAR_Exception::OBSERVER_* constant + * - An array(const PEAR_Exception::OBSERVER_*, + * mixed $options) + * @param string $label The name of the observer. Use this if you want + * to remove it later with removeObserver() */ - public static function addObserver($callback, $label = 'default') { self::$_observers[$label] = $callback; } - public static function delObserver($label = 'default') + public static function removeObserver($label = 'default') { unset(self::$_observers[$label]); } - private function _signal() + /** + * @return int unique identifier for an observer + */ + public static function getUniqueId() + { + return self::$_uniqueid++; + } + + private function signal() { foreach (self::$_observers as $func) { if (is_callable($func)) { @@ -156,15 +170,15 @@ class PEAR_Exception extends Exception } settype($func, 'array'); switch ($func[0]) { - case PEAR_OBSERVER_PRINT: + case self::OBSERVER_PRINT : $f = (isset($func[1])) ? $func[1] : '%s'; printf($f, $this->getMessage()); break; - case PEAR_OBSERVER_TRIGGER: + case self::OBSERVER_TRIGGER : $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; trigger_error($this->getMessage(), $f); break; - case PEAR_OBSERVER_DIE: + case self::OBSERVER_DIE : $f = (isset($func[1])) ? $func[1] : '%s'; die(printf($f, $this->getMessage())); break; @@ -174,48 +188,171 @@ class PEAR_Exception extends Exception } } - private function _getCauseMessage() + /** + * Return specific error information that can be used for more detailed + * error messages or translation. + * + * This method may be overridden in child exception classes in order + * to add functionality not present in PEAR_Exception and is a placeholder + * to define API + * + * The returned array must be an associative array of parameter => value like so: + *
+     * array('name' => $name, 'context' => array(...))
+     * 
+ * @return array + */ + public function getErrorData() { - $msg = " #{$this->_method} at {$this->file} ({$this->line})\n" . - " {$this->message}\n"; - if ($this->cause instanceof Exception) { - return $this->cause->_getCauseMessage() . $msg; - } - return $msg; + return array(); } /** - * @return Exception_object The context of the exception + * Returns the exception that caused this exception to be thrown + * @access public + * @return Exception|array The context of the exception */ public function getCause() { return $this->cause; } + /** + * Function must be public to call on caused exceptions + * @param array + */ + public function getCauseMessage(&$causes) + { + $trace = $this->getTraceSafe(); + $cause = array('class' => get_class($this), + 'message' => $this->message, + 'file' => 'unknown', + 'line' => 'unknown'); + if (isset($trace[0])) { + if (isset($trace[0]['file'])) { + $cause['file'] = $trace[0]['file']; + $cause['line'] = $trace[0]['line']; + } + } + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } + if (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } elseif (is_array($cause) && isset($cause['message'])) { + // PEAR_ErrorStack warning + $causes[] = array( + 'class' => $cause['package'], + 'message' => $cause['message'], + 'file' => isset($cause['context']['file']) ? + $cause['context']['file'] : + 'unknown', + 'line' => isset($cause['context']['line']) ? + $cause['context']['line'] : + 'unknown', + ); + } + } + } + } + + public function getTraceSafe() + { + if (!isset($this->_trace)) { + $this->_trace = $this->getTrace(); + if (empty($this->_trace)) { + $backtrace = debug_backtrace(); + $this->_trace = array($backtrace[count($backtrace)-1]); + } + } + return $this->_trace; + } + public function getErrorClass() { - return $this->error_class; + $trace = $this->getTraceSafe(); + return $trace[0]['class']; } public function getErrorMethod() { - return $this->error_method; + $trace = $this->getTraceSafe(); + return $trace[0]['function']; } public function __toString() { - $str = get_class($this) . " occurred: \n" . - " Error message: {$this->message}\n" . - " Error code : {$this->code}\n" . - " File (Line) : {$this->file} ({$this->line})\n" . - " Method : {$this->_method}\n"; - if ($this->cause instanceof Exception) { - $str .= " Nested Error :\n" . $this->_getCauseMessage(); - } if (isset($_SERVER['REQUEST_URI'])) { - return nl2br('
'.htmlentities($str).'
'); + return $this->toHtml(); + } + return $this->toText(); + } + + public function toHtml() + { + $trace = $this->getTraceSafe(); + $causes = array(); + $this->getCauseMessage($causes); + $html = '' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '\n"; + } + $html .= '' . "\n" + . '' + . '' + . '' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '' + . '' + . '' . "\n"; + } + $html .= '' + . '' + . '' . "\n" + . '
' + . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' + . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' + . 'on line ' . $cause['line'] . '' + . "
Exception trace
#FunctionLocation
' . $k . ''; + if (!empty($v['class'])) { + $html .= $v['class'] . $v['type']; + } + $html .= $v['function']; + $args = array(); + if (!empty($v['args'])) { + foreach ($v['args'] as $arg) { + if (is_null($arg)) $args[] = 'null'; + elseif (is_array($arg)) $args[] = 'Array'; + elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; + elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; + elseif (is_int($arg) || is_double($arg)) $args[] = $arg; + else { + $arg = (string)$arg; + $str = htmlspecialchars(substr($arg, 0, 16)); + if (strlen($arg) > 16) $str .= '…'; + $args[] = "'" . $str . "'"; + } + } + } + $html .= '(' . implode(', ',$args) . ')' + . '' . $v['file'] . ':' . $v['line'] . '
' . ($k+1) . '{main} 
'; + return $html; + } + + public function toText() + { + $causes = array(); + $this->getCauseMessage($causes); + $causeMsg = ''; + foreach ($causes as $i => $cause) { + $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' + . $cause['message'] . ' in ' . $cause['file'] + . ' on line ' . $cause['line'] . "\n"; } - return $str; + return $causeMsg . $this->getTraceAsString(); } } diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php index 35a47fb01d..af4ae5b62e 100644 --- a/pear/PEAR/Installer.php +++ b/pear/PEAR/Installer.php @@ -165,7 +165,14 @@ class PEAR_Installer extends PEAR_Downloader include_once "OS/Guess.php"; $os = new OS_Guess(); } - if (!$os->matchSignature($atts['platform'])) { + if (strlen($atts['platform']) && $atts['platform']{0} == '!') { + $negate = true; + $platform = substr($atts['platform'], 1); + } else { + $negate = false; + $platform = $atts['platform']; + } + if ((bool) $os->matchSignature($platform) === $negate) { $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); return PEAR_INSTALLER_SKIPPED; } @@ -791,25 +798,24 @@ class PEAR_Installer extends PEAR_Downloader foreach ($built as $ext) { $bn = basename($ext['file']); list($_ext_name, $_ext_suff) = explode('.', $bn); - - if ($_ext_suff == '.so' || $_ext_suff == '.dll' /* || something more portable */) { - /* it is an extension */ + if ($_ext_suff == '.so' || $_ext_suff == '.dll') { if (extension_loaded($_ext_name)) { - $this->raiseError( - "Extension '$_ext_name' already loaded. Please unload it ". - "from your php.ini file prior to install or upgrade it."); + $this->raiseError("Extension '$_ext_name' already loaded. " . + 'Please unload it in your php.ini file ' . + 'prior to install or upgrade'); } $role = 'ext'; } else { $role = 'src'; } - - $this->log(1, "Installing $ext[file]\n"); - $copyto = $this->_prependPath($ext['dest'], $this->installroot); + $dest = $ext['dest']; + $this->log(1, "Installing '$ext[file]'"); + $copyto = $this->_prependPath($dest, $this->installroot); $copydir = dirname($copyto); if (!@is_dir($copydir)) { if (!$this->mkDirHier($copydir)) { - return $this->raiseError("failed to mkdir $copydir", PEAR_INSTALLER_FAILED); + return $this->raiseError("failed to mkdir $copydir", + PEAR_INSTALLER_FAILED); } $this->log(3, "+ mkdir $copydir"); } @@ -821,15 +827,15 @@ class PEAR_Installer extends PEAR_Downloader $mode = 0666 & ~(int)octdec($this->config->get('umask')); $this->addFileOperation('chmod', array($mode, $copyto)); if (!@chmod($copyto, $mode)) { - $this->log(0, "failed to chamge mode of $copyto"); + $this->log(0, "failed to change mode of $copyto"); } } $this->addFileOperation('rename', array($ext['file'], $copyto)); - + $pkginfo['filelist'][$bn] = array( 'role' => $role, - 'installed_as' => $ext['dest'], - 'php_api' => $ext['php_api'], + 'installed_as' => $dest, + 'php_api' => $ext['php_api'], 'zend_mod_api' => $ext['zend_mod_api'], 'zend_ext_api' => $ext['zend_ext_api'], ); diff --git a/pear/PEAR/Registry.php b/pear/PEAR/Registry.php index f85bbfdd56..631328bea9 100644 --- a/pear/PEAR/Registry.php +++ b/pear/PEAR/Registry.php @@ -286,7 +286,9 @@ class PEAR_Registry extends PEAR $open_mode = 'r'; } - $this->lock_fp = @fopen($this->lockfile, $open_mode); + if (!is_resource($this->lock_fp)) { + $this->lock_fp = @fopen($this->lockfile, $open_mode); + } if (!is_resource($this->lock_fp)) { return $this->raiseError("could not create lock file" . @@ -312,6 +314,9 @@ class PEAR_Registry extends PEAR function _unlock() { $ret = $this->_lock(LOCK_UN); + if (is_resource($this->lock_fp)) { + fclose($this->lock_fp); + } $this->lock_fp = null; return $ret; } diff --git a/pear/package-PEAR.xml b/pear/package-PEAR.xml index 4811c9dfbc..6aa1690033 100644 --- a/pear/package-PEAR.xml +++ b/pear/package-PEAR.xml @@ -4,22 +4,22 @@ PEAR PEAR Base System The PEAR package contains: - * the PEAR base class - * the PEAR_Error error handling mechanism - * the alpha-quality PEAR_ErrorStack advanced error handling mechanism * the PEAR installer, for creating, distributing and installing packages + * the alpha-quality PEAR_Exception php5-only exception class + * the beta-quality PEAR_ErrorStack advanced error handling mechanism + * the PEAR_Error error handling mechanism * the OS_Guess class for retrieving info about the OS where PHP is running on * the System class for quick handling common operations with files and directories + * the PEAR base class - PHP License ssb lead - Stig Sæther Bakken + Stig Bakken stig@php.net @@ -29,10 +29,10 @@ cox@idecnet.com - mj - developer - Martin Jansen - mj@php.net + cellog + lead + Greg Beaver + cellog@php.net pajoye @@ -41,32 +41,30 @@ pajoye@pearfr.org - cellog - lead - Greg Beaver - cellog@php.net + mj + developer + Martin Jansen + mj@php.net - 1.3.2 - 2004-04-06 + 1.3.5 + 2005-02-18 stable + PHP License -Installer: - * fix Bug #1186 raise a notice error on PEAR::Common $_packageName - * fix Bug #1249 display the right state when using --force option + * fix Bug #3505: pecl can't install PDO + * enhance pear run-tests dramatically + * fix Bug #3506: pear install should export the pear version into the environment - - - - + + + - - @@ -78,22 +76,25 @@ Installer: + + + + + + - - - - + + + - - - + @@ -114,6 +115,10 @@ Installer: + + + + @@ -147,22 +152,49 @@ PEAR_ErrorStack: - 1.3 - 2004-02-20 + 1.3.3 + 2004-10-28 stable -PEAR Installer: - -* Bug #171 --alldeps with a rel="eq" should install the required version, if possible -* Bug #249 installing from an url doesnt work -* Bug #248 --force command does not work as expected -* Bug #293 [Patch] PEAR_Error not calling static method callbacks for error-handler -* Bug #324 pear -G gives Fatal Error (PHP-GTK not installed, but error is at engine level) -* Bug #594 PEAR_Common::analyzeSourceCode fails on string with $var and { -* Bug #521 Incorrect filename in naming warnings -* Moved download code into its own class -* Fully unit tested the installer, packager, downloader, and PEAR_Common +Installer: + * fix Bug #1186 raise a notice error on PEAR::Common $_packageName + * fix Bug #1249 display the right state when using --force option + * fix Bug #2189 upgrade-all stops if dependancy fails + * fix Bug #1637 The use of interface causes warnings when packaging with PEAR + * fix Bug #1420 Parser bug for T_DOUBLE_COLON + * fix Request #2220 pear5 build fails on dual php4/php5 system + * fix Bug #1163 pear makerpm fails with packages that supply role="doc" +Other: + * add PEAR_Exception class for PHP5 users + * fix critical problem in package.xml for linux in 1.3.2 + * fix staticPopCallback() in PEAR_ErrorStack + * fix warning in PEAR_Registry for windows 98 users + + + + 1.3.3.1 + 2004-11-08 + stable + + add RunTest.php to package.xml, make run-tests display failed tests, and use ui + + + + 1.3.4 + 2005-01-01 + stable + + * fix a serious problem caused by a bug in all versions of PHP that caused multiple registration + of the shutdown function of PEAR.php + * fix Bug #2861: package.dtd does not define NUMBER + * fix Bug #2946: ini_set warning errors + * fix Bug #3026: Dependency type "ne" is needed, "not" is not handled + properly + * fix Bug #3061: potential warnings in PEAR_Exception + * implement Request #2848: PEAR_ErrorStack logger extends, PEAR_ERRORSTACK_DIE + * implement Request #2914: Dynamic Include Path for run-tests command + * make pear help listing more useful (put how-to-use info at the bottom of the listing) diff --git a/pear/package.dtd b/pear/package.dtd index 45beb7ba84..d16c540b7d 100644 --- a/pear/package.dtd +++ b/pear/package.dtd @@ -1,5 +1,5 @@ - + @@ -65,8 +65,8 @@ outputData('WARNING: running in safe mode requires that all files created ' . + 'be the same uid as the current script. PHP reports this script is uid: ' . + @getmyuid() . ', and current user is: ' . @get_current_user()); +} $pear_user_config = ''; $pear_system_config = ''; @@ -212,9 +217,6 @@ function usage($error = null, $helpsubject = null) $put = cmdHelp($helpsubject); } else { $put = - "Usage: $progname [options] command [command-options] \n". - "Type \"$progname help options\" to list all options.\n". - "Type \"$progname help \" to get the help for the specified command.\n". "Commands:\n"; $maxlen = max(array_map("strlen", $all_commands)); $formatstr = "%-{$maxlen}s %s\n"; @@ -222,6 +224,11 @@ function usage($error = null, $helpsubject = null) foreach ($all_commands as $cmd => $class) { $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); } + $put .= + "Usage: $progname [options] command [command-options] \n". + "Type \"$progname help options\" to list all options.\n". + "Type \"$progname help shortcuts\" to list all command shortcuts.\n". + "Type \"$progname help \" to get the help for the specified command."; } fputs($stderr, "$put\n"); fclose($stderr); diff --git a/pear/template.spec b/pear/template.spec index 9bf356c7f5..f6f91a524e 100644 --- a/pear/template.spec +++ b/pear/template.spec @@ -30,25 +30,29 @@ pear -v -c %{buildroot}/pearrc \ %build echo BuildRoot=%{buildroot} +%clean +[ -n "%{buildroot}" -a "%{buildroot}" != / ] && rm -rf %{buildroot} + %postun pear uninstall --nodeps -r @package@ -rm @rpm_xml_dir@/@package@.xml %post pear install --nodeps -r @rpm_xml_dir@/@package@.xml %install -pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \ - $RPM_SOURCE_DIR/@package@-%{version}.tgz +pear -c "%{buildroot}/pearrc" install --nodeps -R "%{buildroot}" \ + "$RPM_SOURCE_DIR/@package@-%{version}.tgz" rm %{buildroot}/pearrc rm %{buildroot}/%{_libdir}/php/pear/.filemap rm %{buildroot}/%{_libdir}/php/pear/.lock rm -rf %{buildroot}/%{_libdir}/php/pear/.registry -if [ -d "%{buildroot}/docs/@package@/doc" ]; then - rm -rf $RPM_BUILD_DIR/doc - mv %{buildroot}/docs/@package@/doc $RPM_BUILD_DIR - rm -rf %{buildroot}/docs -fi +for DOCDIR in docs doc examples; do + if [ -d "%{buildroot}/docs/@package@/$DOCDIR" ]; then + rm -rf $RPM_BUILD_DIR/$DOCDIR + mv %{buildroot}/docs/@package@/$DOCDIR $RPM_BUILD_DIR + rm -rf %{buildroot}/docs + fi +done mkdir -p %{buildroot}@rpm_xml_dir@ tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package.xml cp -p package.xml %{buildroot}@rpm_xml_dir@/@package@.xml diff --git a/pear/tests/pear_config.phpt b/pear/tests/pear_config.phpt index f98af7eade..7578a8ad8e 100644 --- a/pear/tests/pear_config.phpt +++ b/pear/tests/pear_config.phpt @@ -4,7 +4,6 @@ PEAR_Config --FILE-- -- cgit v1.2.1