]> granicus.if.org Git - php/commitdiff
* support for .tar files in PEAR_Installer
authorStig Bakken <ssb@php.net>
Sun, 7 Apr 2002 10:38:04 +0000 (10:38 +0000)
committerStig Bakken <ssb@php.net>
Sun, 7 Apr 2002 10:38:04 +0000 (10:38 +0000)
* 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
pear/PEAR/Command/Package.php
pear/PEAR/Common.php
pear/PEAR/Installer.php
pear/PEAR/Packager.php

index 2bb4f167e3ac174b0a0b2a8b0e00dc29d862e674..ab1e6aff49d2d42176a1ed6438af6c1aee6ffe31 100644 (file)
@@ -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;
index 84be4056c4329d8be7ff55719a493978ffa83d3f..54a144698c5842281c382cf5bb7deee5c144b59d 100644 (file)
@@ -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('<pear package>',
                              'Shows information about a PEAR package');
+            case 'package-verify':
+                return array('<package.(tgz|tar|xml)>',
+                             '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 == "<?xml") {
+                        $info = $obj->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;
index 5ff230c4b2aab5ee7acb1881627cf2a4ffc28811..f9385bb783d4f16912f0778b0562b842cf540043 100644 (file)
@@ -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 == "<?xml") {
+                    $info = $obj->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
index d632449a9a220baa3d857689a1dd3382b3b98b70..b4a5cbe01442f0a3f4592b14ba0c22b248b922ba 100644 (file)
@@ -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);
             }
         }
 
index e1a6f82312af0b156c65b496451a858c799bdde4..fa79166045ae933889af02d7892a42019ebed4de 100644 (file)
@@ -51,7 +51,6 @@ class PEAR_Packager extends PEAR_Common
 
     function _PEAR_Packager()
     {
-        chdir($this->orig_pwd);
         $this->_PEAR_Common();
     }