From 40ac4a2d6897836eaf2d4324192a0bbf68e7b151 Mon Sep 17 00:00:00 2001 From: Stig Bakken Date: Thu, 14 Nov 2002 23:23:21 +0000 Subject: [PATCH] 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 --- pear/PEAR/Common.php | 2 +- pear/PEAR/Dependency.php | 114 +++++++++++++++++++++++++++------------ pear/PEAR/Installer.php | 54 +++++++++++++++---- 3 files changed, 125 insertions(+), 45 deletions(-) diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php index af5ef9fc43..eeabe3c0a5 100644 --- a/pear/PEAR/Common.php +++ b/pear/PEAR/Common.php @@ -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(); diff --git a/pear/PEAR/Dependency.php b/pear/PEAR/Dependency.php index 15ffa9f157..1717c3d25c 100644 --- a/pear/PEAR/Dependency.php +++ b/pear/PEAR/Dependency.php @@ -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; + } } ?> diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php index 02b1e399a5..21d7bf9235 100644 --- a/pear/PEAR/Installer.php +++ b/pear/PEAR/Installer.php @@ -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; -- 2.40.0