$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;
$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]";
'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',
+ )
+ ),
'doc' => '[testfile|dir ...]
Run regression tests with PHP\'s regression testing script (run-tests.php).',
),
{
$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();
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();
}
function doRunTests($command, $options, $params)
{
+ include_once 'PEAR/RunTest.php';
+ $log = new PEAR_Common;
+ $run = new PEAR_RunTest($log);
+ $tests = array();
+ if (isset($options['recur'])) {
+ $depth = 4;
+ } else {
+ $depth = 1;
+ }
+ 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 {
+ $tests[] = $p;
+ }
+ }
+ foreach ($tests as $t) {
+ $run->run($t);
+ }
+
+ return true;
+ /*
$cwd = getcwd();
$php = $this->config->get('php_bin');
putenv("TEST_PHP_EXECUTABLE=$php");
system($cmd);
}
return true;
+ */
}
// }}}
if (!isset($attr['role'])) {
continue;
}
+ $name = preg_replace('![/:\\\\]!', '/', $name);
if ($attr['role'] == 'doc') {
$info['doc_files'] .= " $name";
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 :-)
// }}}
/**
- * 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
{
* @access private
*/
var $_validPackageFile;
- /**
- * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}
- * @var array
- * @access private
- */
- var $_packageSortTree;
// }}}
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;
}
$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];
}
}
switch ($token) {
+ case T_WHITESPACE:
+ continue;
+ case ';':
+ if ($interface) {
+ $current_function = '';
+ $current_function_level = -1;
+ }
+ break;
case '"':
$inquote = true;
break;
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",
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;
case T_VARIABLE:
$look_for = 0;
continue 2;
+ case T_DOC_COMMENT:
case T_COMMENT:
if (preg_match('!^/\*\*\s!', $data)) {
$lastphpdoc = $data;
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,
);
}
// there are no dependencies
continue;
}
- foreach($alldeps as $info) {
+ $fail = false;
+ foreach ($alldeps as $info) {
if ($info['type'] != 'pkg') {
continue;
}
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)) {
$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'])])) {
*
* 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 <cellog@php.net>
- * @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
*/
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
* @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;
- }
}
/**
* @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);
}
/**
/**
* Set an error code => error message mapping callback
*
- * 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 {
* 'time' => time(),
* 'context' => $context,
* 'message' => $msg,
- * //['repackage' => $err] repackaged error array
+ * //['repackage' => $err] repackaged error array/Exception class
* );
* </code>
*/
$msg = call_user_func_array($this->_msgCallback,
array(&$this, $err));
$err['message'] = $msg;
- }
-
+ }
if ($repackage) {
$err['repackage'] = $repackage;
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;
}
$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);
/**
* 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
// +----------------------------------------------------------------------+
// | Authors: Tomas V.V.Cox <cox@idecnet.com> |
// | Hans Lellelid <hans@velum.net> |
-// | |
+// | Bertrand Mansion <bmansion@mamasam.com> |
+// | Greg Beaver <cellog@php.net> |
// +----------------------------------------------------------------------+
//
// $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:
*
* getCode
* getFile
* getLine
- * getTrace
- * getTraceAsString
+ * getTraceSafe
+ * getTraceSafeAsString
* __toString
*
* 5) Usage example
* @version $Revision$
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
+ * @author Bertrand Mansion <bmansion@mamasam.com>
*
*/
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:
* 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)) {
}
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;
}
}
- 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:
+ * <pre>
+ * array('name' => $name, 'context' => array(...))
+ * </pre>
+ * @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();
+ $causes[] = array('class' => get_class($this),
+ 'message' => $this->message,
+ 'file' => $trace[0]['file'],
+ '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('<pre>'.htmlentities($str).'</pre>');
+ return $this->toHtml();
+ }
+ return $this->toText();
+ }
+
+ public function toHtml()
+ {
+ $trace = $this->getTraceSafe();
+ $causes = array();
+ $this->getCauseMessage($causes);
+ $html = '<table border="1" cellspacing="0">' . "\n";
+ foreach ($causes as $i => $cause) {
+ $html .= '<tr><td colspan="3" bgcolor="#ff9999">'
+ . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
+ . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
+ . 'on line <b>' . $cause['line'] . '</b>'
+ . "</td></tr>\n";
+ }
+ $html .= '<tr><td colspan="3" bgcolor="#aaaaaa" align="center"><b>Exception trace</b></td></tr>' . "\n"
+ . '<tr><td align="center" bgcolor="#cccccc" width="20"><b>#</b></td>'
+ . '<td align="center" bgcolor="#cccccc"><b>Function</b></td>'
+ . '<td align="center" bgcolor="#cccccc"><b>Location</b></td></tr>' . "\n";
+
+ foreach ($trace as $k => $v) {
+ $html .= '<tr><td align="center">' . $k . '</td>'
+ . '<td>';
+ 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) . ')'
+ . '</td>'
+ . '<td>' . $v['file'] . ':' . $v['line'] . '</td></tr>' . "\n";
+ }
+ $html .= '<tr><td align="center">' . ($k+1) . '</td>'
+ . '<td>{main}</td>'
+ . '<td> </td></tr>' . "\n"
+ . '</table>';
+ 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();
}
}
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;
}
$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" .
function _unlock()
{
$ret = $this->_lock(LOCK_UN);
+ fclose($this->lock_fp);
$this->lock_fp = null;
return $ret;
}