Added error codes for the PEAR_Dependency class

Changed the dependency API to have a reference to an error message
string as first arg to all check methods
This commit is contained in:
Stig Bakken 2002-11-14 23:23:21 +00:00
parent 5ca953b10f
commit 40ac4a2d68
3 changed files with 125 additions and 45 deletions

View File

@ -764,7 +764,7 @@ class PEAR_Common extends PEAR
function infoFromString($data)
{
require_once('PEAR/Dependency.php');
if ($error = PEAR_Dependency::checkExtension('xml')) {
if (PEAR_Dependency::checkExtension($error, 'xml')) {
return $this->raiseError($error);
}
$xp = @xml_parser_create();

View File

@ -27,6 +27,12 @@
require_once "PEAR.php";
define('PEAR_DEPENDENCY_MISSING', -1);
define('PEAR_DEPENDENCY_CONFLICT', -2);
define('PEAR_DEPENDENCY_UPGRADE_MINOR', -3);
define('PEAR_DEPENDENCY_UPGRADE_MAJOR', -4);
define('PEAR_DEPENDENCY_BAD_DEPENDENCY', -5);
class PEAR_Dependency
{
function PEAR_Dependency(&$registry)
@ -45,32 +51,33 @@ class PEAR_Dependency
* [name] => HTML_Common
* )
*/
function callCheckMethod($opts)
function callCheckMethod(&$errmsg, $opts)
{
$rel = isset($opts['rel']) ? $opts['rel'] : 'has';
$req = isset($opts['version']) ? $opts['version'] : null;
$name = isset($opts['name']) ? $opts['name'] : null;
$errmsg = '';
switch ($opts['type']) {
case 'pkg':
return $this->checkPackage($name, $req, $rel);
return $this->checkPackage($errmsg, $name, $req, $rel);
break;
case 'ext':
return $this->checkExtension($name, $req, $rel);
return $this->checkExtension($errmsg, $name, $req, $rel);
break;
case 'php':
return $this->checkPHP($req, $rel);
return $this->checkPHP($errmsg, $req, $rel);
break;
case 'prog':
return $this->checkProgram($name);
return $this->checkProgram($errmsg, $name);
break;
case 'os':
return $this->checkOS($name);
return $this->checkOS($errmsg, $name);
break;
case 'sapi':
return $this->checkSAPI($name);
return $this->checkSAPI($errmsg, $name);
break;
case 'zend':
return $this->checkZend($name);
return $this->checkZend($errmsg, $name);
break;
default:
return "'{$opts['type']}' dependency type not supported";
@ -86,7 +93,7 @@ class PEAR_Dependency
*
* @return mixed bool false if no error or the error string
*/
function checkPackage($name, $req = null, $relation = 'has')
function checkPackage(&$errmsg, $name, $req = null, $relation = 'has')
{
if (substr($relation, 0, 2) == 'v.') {
$relation = substr($relation, 2);
@ -94,12 +101,14 @@ class PEAR_Dependency
switch ($relation) {
case 'has':
if (!$this->registry->packageExists($name)) {
return "requires package `$name'";
$errmsg = "requires package `$name'";
return PEAR_DEPENDENCY_MISSING;
}
return false;
case 'not':
if (!$this->registry->packageExists($name)) {
return "conflicts with package `$name'";
$errmsg = "conflicts with package `$name'";
return PEAR_DEPENDENCY_CONFLICT;
}
return false;
case 'lt':
@ -112,12 +121,14 @@ class PEAR_Dependency
if (!$this->registry->packageExists($name)
|| !version_compare("$version", "$req", $relation))
{
return "requires package `$name' " .
$this->signOperator($relation) . " $req";
$errmsg = "requires package `$name' " .
$this->signOperator($relation) . " $req";
$code = $this->codeFromRelation($relation, $version, $req);
}
return false;
}
return "Relation '$relation' with requirement '$req' is not supported (name=$name)";
$errmsg = "relation '$relation' with requirement '$req' is not supported (name=$name)";
return PEAR_DEPENDENCY_BAD_DEPENDENCY;
}
/**
@ -129,25 +140,29 @@ class PEAR_Dependency
*
* @return mixed bool false if no error or the error string
*/
function checkExtension($name, $req = null, $relation = 'has')
function checkExtension(&$errmsg, $name, $req = null, $relation = 'has')
{
// XXX (ssb): could we avoid loading the extension here?
if (!PEAR::loadExtension($name)) {
return "'$name' PHP extension is not installed";
$errmsg = "'$name' PHP extension is not installed";
return PEAR_DEPENDENCY_MISSING;
}
if ($relation == 'has') {
return false;
}
$code = false;
if (substr($relation, 0, 2) == 'v.') {
$ext_ver = phpversion($name);
$operator = substr($relation, 2);
// Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90)
settype($req, "string");
if (!version_compare("$ext_ver", "$req", $operator)) {
return "'$name' PHP extension version " .
$this->signOperator($operator) . " $req is required";
$retval = "'$name' PHP extension version " .
$this->signOperator($operator) . " $req is required";
$code = $this->codeFromRelation($relation, $ext_ver, $req);
}
}
return false;
return $code;
}
/**
@ -157,16 +172,21 @@ class PEAR_Dependency
*
* @return mixed bool false if no error or the error string
*/
function checkOS($os)
function checkOS(&$errmsg, $os)
{
// XXX Fixme: Implement a more flexible way, like
// comma separated values or something similar to PEAR_OS
// only 'has' relation is supported
if ($os == PHP_OS) {
static $myos;
if (empty($myos)) {
include_once "OS/Guess.php";
$myos = new OS_Guess();
}
// only 'has' relation is currently supported
if ($myos->matchSignature($os)) {
return false;
}
return "'$os' operating system not supported";
$errmsg = "'$os' operating system not supported";
return PEAR_DEPENDENCY_CONFLICT;
}
/**
@ -177,14 +197,15 @@ class PEAR_Dependency
*
* @return mixed bool false if no error or the error string
*/
function checkPHP($req, $relation = 'ge')
function checkPHP(&$errmsg, $req, $relation = 'ge')
{
if (substr($relation, 0, 2) == 'v.') {
$php_ver = phpversion();
$operator = substr($relation, 2);
if (!version_compare("$php_ver", "$req", $operator)) {
return "PHP version " . $this->signOperator($operator) .
" $req is required";
$errmsg = "PHP version " . $this->signOperator($operator) .
" $req is required";
return PEAR_DEPENDENCY_CONFLICT;
}
}
return false;
@ -198,7 +219,7 @@ class PEAR_Dependency
*
* @return mixed bool false if no error or the error string
*/
function checkProgram($program)
function checkProgram(&$errmsg, $program)
{
// XXX FIXME honor safe mode
$path_delim = OS_WINDOWS ? ';' : ':';
@ -210,7 +231,8 @@ class PEAR_Dependency
return false;
}
}
return "'$program' program is not present in the PATH";
$errmsg = "'$program' program is not present in the PATH";
return PEAR_DEPENDENCY_MISSING;
}
/**
@ -223,7 +245,7 @@ class PEAR_Dependency
* hardcoded to 'has')
* @return mixed bool false if no error or the error string
*/
function checkSAPI($name, $req = null, $relation = 'has')
function checkSAPI(&$errmsg, $name, $req = null, $relation = 'has')
{
// XXX Fixme: There is no way to know if the user has or
// not other SAPI backends installed than the installer one
@ -234,7 +256,8 @@ class PEAR_Dependency
if ($sapi_backend == $name) {
return false;
}
return "'$sapi_backend' SAPI backend not supported";
$errmsg = "'$sapi_backend' SAPI backend not supported";
return PEAR_DEPENDENCY_CONFLICT;
}
@ -246,14 +269,15 @@ class PEAR_Dependency
*
* @return mixed bool false if no error or the error string
*/
function checkZend($req, $relation = 'ge')
function checkZend(&$errmsg, $req, $relation = 'ge')
{
if (substr($relation, 0, 2) == 'v.') {
$zend_ver = zend_version();
$operator = substr($relation, 2);
if (!version_compare("$zend_ver", "$req", $operator)) {
return "Zend version " . $this->signOperator($operator) .
" $req is required";
$errmsg = "Zend version " . $this->signOperator($operator) .
" $req is required";
return PEAR_DEPENDENCY_CONFLICT;
}
}
return false;
@ -276,6 +300,28 @@ class PEAR_Dependency
return $operator;
}
}
function codeFromRelation($relation, $version, $req)
{
$code = PEAR_DEPENDENCY_BAD_DEPENDENCY;
switch ($relation) {
case 'gt': case 'ge': case 'eq':
// upgrade
$have_major = preg_replace('/\D.*/', '', $version);
$need_major = preg_replace('/\D.*/', '', $req);
if ($need_major > $have_major) {
$code = PEAR_DEPENDENCY_UPGRADE_MAJOR;
} else {
$code = PEAR_DEPENDENCY_UPGRADE_MINOR;
}
break;
case 'lt': case 'le': case 'ne':
$code = PEAR_DEPENDENCY_CONFLICT;
break;
}
return $code;
}
}
?>

View File

@ -156,7 +156,6 @@ class PEAR_Installer extends PEAR_Common
function _installFile($file, $atts, $tmp_path)
{
static $os;
ini_set("track_errors", 1);
if (isset($atts['platform'])) {
if (empty($os)) {
include_once "OS/Guess.php";
@ -305,7 +304,12 @@ class PEAR_Installer extends PEAR_Common
function addFileOperation($type, $data)
{
$this->log(3, "adding to transaction: $type " . implode(" ", $data));
if ($type == 'chmod') {
$octmode = decoct($data[0]);
$this->log(3, "adding to transaction: $type $octmode $data[1]");
} else {
$this->log(3, "adding to transaction: $type " . implode(" ", $data));
}
$this->file_operations[] = array($type, $data);
}
@ -346,7 +350,7 @@ class PEAR_Installer extends PEAR_Common
break;
case 'delete':
// check that directory is writable
if (!is_writable(dirname($data[0]))) {
if (file_exists($data[0]) && !is_writable(dirname($data[0]))) {
$errors[] = "permission denied ($type): $data[0]";
}
break;
@ -370,7 +374,8 @@ class PEAR_Installer extends PEAR_Common
break;
case 'chmod':
@chmod($data[0], $data[1]);
$this->log(3, "+ chmod $data[0] $data[1]");
$octmode = decoct($data[0]);
$this->log(3, "+ chmod $octmode $data[1]");
break;
case 'delete':
@unlink($data[0]);
@ -779,16 +784,45 @@ class PEAR_Installer extends PEAR_Common
function checkDeps(&$pkginfo)
{
$deps = &new PEAR_Dependency($this->registry);
$errors = null;
$depchecker = &new PEAR_Dependency($this->registry);
$error = $errors = '';
$failed_deps = array();
if (is_array($pkginfo['release_deps'])) {
foreach($pkginfo['release_deps'] as $dep) {
if ($error = $deps->callCheckMethod($dep)) {
$errors .= "\n$error";
$code = $depchecker->callCheckMethod($error, $dep);
if ($code) {
$failed_deps[] = array($dep, $code, $error);
}
}
if ($errors) {
return $errors;
$n = count($failed_deps);
if ($n > 0) {
$depinstaller =& new PEAR_Installer($this->ui);
$to_install = array();
for ($i = 0; $i < $n; $i++) {
if (isset($failed_deps[$i]['type'])) {
$type = $failed_deps[$i]['type'];
} else {
$type = 'pkg';
}
switch ($failed_deps[$i][1]) {
case PEAR_DEPENDENCY_MISSING:
if ($type == 'pkg') {
// install
}
$errors .= "\n" . $failed_deps[$i][2];
break;
case PEAR_DEPENDENCY_UPGRADE_MINOR:
if ($type == 'pkg') {
// upgrade
}
$errors .= "\n" . $failed_deps[$i][2];
break;
default:
$errors .= "\n" . $failed_deps[$i][2];
break;
}
}
return substr($errors, 1);
}
}
return false;