From dc974a0299621cab657756b4048b781716da0490 Mon Sep 17 00:00:00 2001 From: Stig Bakken Date: Sun, 7 Apr 2002 10:38:04 +0000 Subject: [PATCH] * support for .tar files in PEAR_Installer * new command: package-verify * "package" command now sanity-checks the package information before making the tarball * -Z option to the install/update commands for downloading non-compressed packages --- pear/PEAR/Command/Install.php | 8 +- pear/PEAR/Command/Package.php | 61 ++++++++++++- pear/PEAR/Common.php | 160 ++++++++++++++++++++++++++++++++-- pear/PEAR/Installer.php | 10 +-- pear/PEAR/Packager.php | 1 - 5 files changed, 224 insertions(+), 16 deletions(-) diff --git a/pear/PEAR/Command/Install.php b/pear/PEAR/Command/Install.php index 2bb4f167e3a..ab1e6aff49d 100644 --- a/pear/PEAR/Command/Install.php +++ b/pear/PEAR/Command/Install.php @@ -78,7 +78,8 @@ class PEAR_Command_Install extends PEAR_Command_Common " -f forces the installation of the package\n". " when it is already installed\n". " -n do not take care of package dependencies\n". - " -s soft update: install or upgrade only if needed"; + " -s soft update: install or upgrade only if needed". + " -Z no compression: download plain .tar files"; return $ret; } @@ -87,7 +88,7 @@ class PEAR_Command_Install extends PEAR_Command_Common function getOptions() { - return array('f', 'n', 's'); + return array('f', 'n', 's', 'Z'); } // }}} @@ -112,6 +113,9 @@ class PEAR_Command_Install extends PEAR_Command_Common if (isset($options['s'])) { $opts['soft'] = true; } + if (isset($options['Z'])) { + $opts['nocompress'] = true; + } switch ($command) { case 'upgrade': $opts['upgrade'] = true; diff --git a/pear/PEAR/Command/Package.php b/pear/PEAR/Command/Package.php index 84be4056c43..54a144698c5 100644 --- a/pear/PEAR/Command/Package.php +++ b/pear/PEAR/Command/Package.php @@ -48,12 +48,15 @@ class PEAR_Command_Package extends PEAR_Command_Common function getCommands() { return array('package', + 'package-info', 'package-list', - 'package-info'); + 'package-verify'); } // }}} + // {{{ getHelp() + function getHelp($command) { switch ($command) { @@ -67,9 +70,13 @@ class PEAR_Command_Package extends PEAR_Command_Common case 'packge-info': return array('', 'Shows information about a PEAR package'); + case 'package-verify': + return array('', + 'Verifies a package or description file'); } } + // }}} // {{{ run() @@ -94,12 +101,26 @@ class PEAR_Command_Package extends PEAR_Command_Common // {{{ package case 'package': { - $pkginfofile = isset($params[0]) ? $params[0] : null; + $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; ob_start(); $packager =& new PEAR_Packager($this->config->get('php_dir'), $this->config->get('ext_dir'), $this->config->get('doc_dir')); $packager->debug = $this->config->get('verbose'); + $err = $warn = array(); + $packager->validateInfo($pkginfofile, $err, $warn); + foreach ($err as $e) { + $this->ui->displayLine("Error: $e"); + } + foreach ($warn as $w) { + $this->ui->displayLine("Warning: $w"); + } + $this->ui->displayLine(sprintf('%d error(s), %d warning(s)', + sizeof($err), sizeof($warn))); + if (sizeof($err) > 0) { + $this->ui->displayLine("Fix these errors and try again."); + break; + } $result = $packager->Package($pkginfofile); $output = ob_get_contents(); ob_end_clean(); @@ -240,6 +261,42 @@ class PEAR_Command_Package extends PEAR_Command_Common break; } + // }}} + // {{{ package-verify + + case 'package-verify': { + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = new PEAR_Common; + $info = null; + $validate_result = $obj->validatePackageInfo($info, $err, $warn); + if (file_exists($params[0])) { + $fp = fopen($params[0], "r"); + $test = fread($fp, 5); + fclose($fp); + if ($test == "infoFromDescriptionFile($params[0]); + } + } + if (empty($info)) { + $info = $obj->infoFromTgzFile($params[0]); + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + foreach ($err as $e) { + $this->ui->displayLine("Error: $e"); + } + foreach ($warn as $w) { + $this->ui->displayLine("Warning: $w"); + } + $this->ui->displayLine(sprintf('%d error(s), %d warning(s)', + sizeof($err), sizeof($warn))); + break; + } + // }}} default: { return false; diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php index 5ff230c4b2a..f9385bb783d 100644 --- a/pear/PEAR/Common.php +++ b/pear/PEAR/Common.php @@ -57,16 +57,34 @@ class PEAR_Common extends PEAR var $pkginfo = array(); /** - * Permitted maintainer roles + * Valid maintainer roles * @var array */ var $maintainer_roles = array('lead','developer','contributor','helper'); /** - * Permitted release states + * Valid release states * @var array */ - var $releases_states = array('alpha','beta','stable','snapshot','devel'); + var $release_states = array('alpha','beta','stable','snapshot','devel'); + + /** + * Valid dependency types + * @var array + */ + var $dependency_types = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); + + /** + * Valid dependency relations + * @var array + */ + var $dependency_relations = array('has','eq','lt','le','gt','ge'); + + /** + * Valid file roles + * @var array + */ + var $file_roles = array('php','ext','test','doc','data','extsrc'); /** * User Interface object (PEAR_Frontend_* class). If null, @@ -417,9 +435,9 @@ class PEAR_Common extends PEAR } break; case 'state': - if (!in_array($data, $this->releases_states)) { + /* if (!in_array($data, $this->release_states)) { trigger_error("The release state: '$data' is not valid", E_USER_WARNING); - } elseif ($this->in_changelog) { + } else*/if ($this->in_changelog) { $this->current_release['release_state'] = $data; } else { $this->pkginfo['release_state'] = $data; @@ -549,7 +567,12 @@ class PEAR_Common extends PEAR if (!@is_file($file)) { return $this->raiseError('tgz :: could not open file'); } - $tar = new Archive_Tar($file, true); + if (substr($file, -4) == '.tar') { + $compress = false; + } else { + $compress = true; + } + $tar = new Archive_Tar($file, $compress); $content = $tar->listContent(); if (!is_array($content)) { return $this->raiseError('tgz :: could not get contents of package'); @@ -774,6 +797,131 @@ class PEAR_Common extends PEAR return $ret; } + // }}} + // {{{ validatePackageInfo() + + function validatePackageInfo($info, &$errors, &$warnings) + { + if (is_string($info) && file_exists($info)) { + $tmp = substr($info, -4); + if ($tmp == '.xml') { + $info = $this->infoFromDescriptionFile($info); + } elseif ($tmp == '.tar' || $tmp == '.tgz') { + $info = $this->infoFromTgzFile($info); + } else { + $fp = fopen($params[0], "r"); + $test = fread($fp, 5); + fclose($fp); + if ($test == "infoFromDescriptionFile($params[0]); + } else { + $info = $obj->infoFromTgzFile($params[0]); + } + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + } + if (!is_array($info)) { + return false; + } + $errors = array(); + $warnings = array(); + if (empty($info['package'])) { + $errors[] = 'missing package name'; + } + if (empty($info['summary'])) { + $errors[] = 'missing summary'; + } elseif (strpos(trim($info['summary']), "\n") !== false) { + $warnings[] = 'summary should be on a single line'; + } + if (empty($info['description'])) { + $errors[] = 'missing description'; + } + if (empty($info['release_license'])) { + $errors[] = 'missing license'; + } + if (empty($info['version'])) { + $errors[] = 'missing version'; + } + if (empty($info['release_state'])) { + $errors[] = 'missing release state'; + } elseif (!in_array($info['release_state'], $this->release_states)) { + $errors[] = "invalid release state `$info[release_state]', should be one of: ".implode(' ', $this->release_states); + } + if (empty($info['release_date'])) { + $errors[] = 'missing release date'; + } elseif (!preg_match('/^\d{4}-\d\d-\d\d$/', $info['release_date'])) { + $errors[] = "invalid release date `$info[release_date]', format is YYYY-MM-DD"; + } + if (empty($info['release_notes'])) { + $errors[] = "missing release notes"; + } + if (empty($info['maintainers'])) { + $errors[] = 'no maintainer(s)'; + } else { + $i = 1; + foreach ($info['maintainers'] as $m) { + if (empty($m['handle'])) { + $errors[] = "maintainer $i: missing handle"; + } + if (empty($m['role'])) { + $errors[] = "maintainer $i: missing role"; + } elseif (!in_array($m['role'], $this->maintainer_roles)) { + $errors[] = "maintainer $i: invalid role `$m[role]', should be one of: ".implode(' ', $this->maintainer_roles); + } + if (empty($m['name'])) { + $errors[] = "maintainer $i: missing name"; + } + if (empty($m['email'])) { + $errors[] = "maintainer $i: missing email"; + } + $i++; + } + } + if (!empty($info['deps'])) { + $i = 1; + foreach ($info['deps'] as $d) { + if (empty($d['type'])) { + $errors[] = "depenency $i: missing type"; + } elseif (!in_array($d['type'], $this->dependency_types)) { + $errors[] = "depenency $i: invalid type, should be one of: ".implode(' ', $this->depenency_types); + } + if (empty($d['rel'])) { + $errors[] = "dependency $i: missing relation"; + } elseif (!in_array($d['rel'], $this->dependency_relations)) { + $errors[] = "dependency $i: invalid relation, should be one of: ".implode(' ', $this->dependency_relations); + } + if ($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"; + } + 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"; + } + $i++; + } + } + if (empty($info['filelist'])) { + $errors[] = 'no files'; + } else { + foreach ($info['filelist'] as $file => $fa) { + if (empty($fa['role'])) { + $errors[] = "$file: missing role"; + } elseif (!in_array($fa['role'], $this->file_roles)) { + $errors[] = "$file: invalid role, should be one of: ".implode(' ', $this->file_roles); + } elseif ($fa['role'] == 'extsrc' && empty($fa['sources'])) { + $errors[] = "$file: no source files"; + } + // Any checks we can do for baseinstalldir? + } + } + return true; + } + // }}} } ?> \ No newline at end of file diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php index d632449a9a2..b4a5cbe0144 100644 --- a/pear/PEAR/Installer.php +++ b/pear/PEAR/Installer.php @@ -88,11 +88,11 @@ class PEAR_Installer extends PEAR_Common function _deletePackageFiles($package) { - $info = $this->registry->packageInfo($package); - if ($info == null) { + $filelist = $this->registry->packageInfo($package, 'filelist'); + if ($filelist == null) { return $this->raiseError("$package not installed"); } - foreach ($info['filelist'] as $file => $props) { + foreach ($filelist as $file => $props) { $path = $props['installed_as']; // XXX TODO: do a "rmdir -p dirname($path)" to maintain clean the fs if (!@unlink($path)) { @@ -264,7 +264,7 @@ class PEAR_Installer extends PEAR_Common // ==> XXX This part should be removed later on $flag_old_format = false; if (!is_file($descfile)) { - // ----- Look for old package .tgz archive format + // ----- Look for old package archive format // In this format the package.xml file was inside the package directory name $dp = opendir($tmpdir); do { @@ -320,7 +320,7 @@ class PEAR_Installer extends PEAR_Common } if (empty($options['register_only'])) { // when upgrading, remove old release's files first: - $this->_deletePackageFiles($package); + $this->_deletePackageFiles($pkgname); } } diff --git a/pear/PEAR/Packager.php b/pear/PEAR/Packager.php index e1a6f82312a..fa79166045a 100644 --- a/pear/PEAR/Packager.php +++ b/pear/PEAR/Packager.php @@ -51,7 +51,6 @@ class PEAR_Packager extends PEAR_Common function _PEAR_Packager() { - chdir($this->orig_pwd); $this->_PEAR_Common(); }