]> granicus.if.org Git - php/commitdiff
- remove the xml parser code (use PEAR_Common::infoFromDescFile)
authorTomas V.V.Cox <cox@php.net>
Wed, 18 Jul 2001 17:29:09 +0000 (17:29 +0000)
committerTomas V.V.Cox <cox@php.net>
Wed, 18 Jul 2001 17:29:09 +0000 (17:29 +0000)
- added the new package.xml Dir tag support
- killed many bugs and warnings

(as it is quite usable yet, work is still in progress)

pear/PEAR/Installer.php

index 5a650a4ba38e183176d3a3e10d7084a255ed9ad5..47797003407ab1c9f04ef0e2114b6c1d810f99ca 100644 (file)
 // | license@php.net so we can mail you a copy immediately.               |
 // +----------------------------------------------------------------------+
 // | Authors: Stig Bakken <ssb@fast.no>                                   |
-// |                                                                      |
+// |          Tomas V.V.Cox <cox@idecnet.com>                             |
 // +----------------------------------------------------------------------+
 //
+// $Id$
 
 require_once "PEAR/Common.php";
 
@@ -24,6 +25,12 @@ require_once "PEAR/Common.php";
  * Administration class used to install PEAR packages and maintain the
  * installed package database.
  *
+ * TODO:
+ *  - move the package db handler methods to its own class.
+ *  - install also the package.xml?
+ *  - remove unneeded code
+ *  - only decrompress pack once
+ *
  * @since PHP 4.0.2
  * @author Stig Bakken <ssb@fast.no>
  */
@@ -76,7 +83,6 @@ class PEAR_Installer extends PEAR_Common
         $this->extdir = $extdir;
         $this->docdir = $docdir;
         $this->statedir = "/var/lib/php"; // XXX FIXME Windows
-        $this->loadPackageList("$this->statedir/packages.lst");
     }
 
     // }}}
@@ -84,10 +90,11 @@ class PEAR_Installer extends PEAR_Common
 
     function _PEAR_Installer()
     {
+        chdir($this->pwd);
         if ($this->tmpdir && is_dir($this->tmpdir)) {
             system("rm -rf $this->tmpdir"); // XXX FIXME Windows
         }
-        if ($this->pkglist_fp && is_resource($this->pkglist_fp)) {
+        if (isset($this->pkglist_fp) && is_resource($this->pkglist_fp)) {
             flock($this->pkglist_fp, LOCK_UN);
             fclose($this->pkglist_fp);
         }
@@ -98,36 +105,6 @@ class PEAR_Installer extends PEAR_Common
 
     // }}}
 
-    // {{{ mkDirHier()
-
-    function mkDirHier($dir)
-    {
-        $dirstack = array();
-        while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) {
-            array_unshift($dirstack, $dir);
-            $dir = dirname($dir);
-        }
-        while ($newdir = array_shift($dirstack)) {
-            if (mkdir($newdir, 0777)) {
-                $this->log(1, "created dir $newdir");
-            } else {
-                return $this->raiseError("mkdir($newdir) failed");
-            }
-        }
-    }
-
-    // }}}
-    // {{{ log()
-
-    function log($level, $msg)
-    {
-        if ($this->debug >= $level) {
-            print "$msg\n";
-        }
-    }
-
-    // }}}
-
     // {{{ lockPackageList()
 
     function lockPackageList()
@@ -234,7 +211,151 @@ class PEAR_Installer extends PEAR_Common
      *
      * @return bool true if successful, false if not
      */
+
     function install($pkgfile)
+    {
+        // XXX FIXME Add here code to manage packages database
+        //$this->loadPackageList("$this->statedir/packages.lst");
+        $this->pwd = getcwd();
+        $need_download = false;
+        if (preg_match('#^(http|ftp)://#', $pkgfile)) {
+            $need_download = true;
+        } elseif (!@is_file($pkgfile)) {
+            return $this->raiseError("$pkgfile: no such file");
+        }
+        // Download package -----------------------------------------------
+        if ($need_download) {
+            $file = basename($pkgfile);
+            // XXX FIXME use ??? on Windows, use $TMPDIR on unix (use tmpnames?)
+            $downloaddir = '/tmp/pearinstall';
+            if (!$this->mkDirHier($downloaddir)) {
+                return $this->raiseError("Failed to create tmp dir: $downloaddir");
+            }
+            $downloadfile = $downloaddir.DIRECTORY_SEPARATOR.$file;
+            $this->log(1, "downloading $pkgfile ...");
+            if (!$fp = @fopen($pkgfile, 'r')) {
+                return $this->raiseError("$pkgfile: failed to download ($php_errormsg)");
+            }
+            if (!$wp = @fopen($downloadfile, 'w')) {
+                return $this->raiseError("$downloadfile: write failed ($php_errormsg)");
+            }
+            $this->addTempFile($downloadfile);
+            $bytes = 0;
+            while ($data = @fread($fp, 16384)) {
+                $bytes += strlen($data);
+                if (!@fwrite($wp, $data)) {
+                    return $this->raiseError("$downloadfile: write failed ($php_errormsg)");
+                }
+            }
+            $pkgfile = $downloadfile;
+            fclose($fp);
+            fclose($wp);
+            $this->log(1, '...done: ' . number_format($bytes, 0, '', ',') . ' bytes');
+        }
+        // Test for package.xml -------------------------------------------
+        // XXX FIXME only decompress once
+        $fp = popen("gzip -dc $pkgfile | tar -tf -", 'r');
+        if (!$fp) {
+            return $this->raiseError("Unable to examine $pkgfile (gzip or tar failed)");
+        }
+        while ($line = fgets($fp, 4096)) {
+            $line = rtrim($line);
+            if (preg_match('!^[^/]+/package.xml$!', $line)) {
+                if (isset($descfile)) {
+                    return $this->raiseError("Invalid package: multiple package.xml files at depth one!");
+                }
+                $descfile = $line;
+            }
+        }
+        pclose($fp);
+        if (!$descfile) {
+            return $this->raiseError("Invalid package: no package.xml file found!");
+        }
+
+        // Decompress pack in tmp dir -------------------------------------
+        // XXX FIXME Windows
+        $this->tmpdir = tempnam("/tmp", "pear");
+        unlink($this->tmpdir);
+        if (!mkdir($this->tmpdir, 0755)) {
+            return $this->raiseError("Unable to create temporary directory $this->tmpdir.");
+        } else {
+            $this->log(2, '...tmp dir created at ' . $this->tmpdir);
+        }
+        $this->addTempFile($this->tmpdir);
+
+
+        // XXX FIXME Windows should check for drive
+        if (substr($pkgfile, 0, 1) == DIRECTORY_SEPARATOR) {
+            $pkgfilepath = $pkgfile;
+        } else {
+            $pkgfilepath = $this->pwd . DIRECTORY_SEPARATOR . $pkgfile;
+        }
+
+        if (!chdir($this->tmpdir)) {
+            return $this->raiseError("Unable to chdir to $this->tmpdir.");
+        }
+        // XXX FIXME Windows
+        system("gzip -dc $pkgfilepath | tar -xf -");
+        $this->log(2, "launched command: gzip -dc $pkgfilepath | tar -xf -");
+        if (!is_file($descfile)) {
+            $this->log(2, "No desc file found: $descfile");
+            return $this->raiseError("No package.xml file after extracting the archive.");
+        }
+
+        // Parse xml file -----------------------------------------------
+        $pkginfo = $this->infoFromDescriptionFile($descfile);
+        if (PEAR::isError($pkginfo)) {
+            return $pkginfo;
+        }
+
+        // Copy files to dest dir ---------------------------------------
+        if (!is_dir($this->phpdir)) {
+            return $this->raiseError("No script destination directory found\n",
+                                     null, PEAR_ERROR_DIE);
+        }
+        foreach ($pkginfo['filelist'] as $fname => $atts) {
+            $dest_dir = $this->phpdir . DIRECTORY_SEPARATOR . dirname($fname);
+            $fname = dirname($descfile) . DIRECTORY_SEPARATOR . $fname;
+            $this->_copyFile($fname, $dest_dir, $atts);
+        }
+        return true;
+    }
+
+    function _copyFile($file, $dest_dir, $atts)
+    {
+        $type = strtolower($atts["Role"]);
+        switch ($type) {
+            case "test":
+                // don't install test files for now
+                $this->log(2, "+ Test file $file won't be installed yet");
+                return true;
+                break;
+            case 'doc':
+            case 'php':
+            default:
+                $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
+                break;
+        }
+        if (!@is_dir($dest_dir)) {
+            if (!$this->mkDirHier($dest_dir)) {
+                $this->log(0, "failed to mkdir $dest_dir");
+                return false;
+            }
+            $this->log(2, "+ created dir $dest_dir");
+        }
+        if (!@copy($file, $dest_file)) {
+            $this->log(0, "failed to copy $file to $dest_file");
+            return false;
+        }
+        $this->log(2, "+ copy $file to $dest_file");
+        // FIXME Update Package database here
+        //$this->updatePackageListFrom("$d/$file");
+        $this->log(1, "installed file $dest_file");
+        return true;
+    }
+
+    /* REMOVEME: This is the old code
+    function _install($pkgfile)
     {
         if (preg_match('#^(http|ftp)://#', $pkgfile)) {
             $need_download = true;
@@ -356,12 +477,10 @@ class PEAR_Installer extends PEAR_Common
         $this->current_attributes = $attribs;
         switch ($name) {
             case "Package":
-/*
-                if (strtolower($attribs["Type"]) != "binary") {
-                    return $this->raiseError("Invalid package: only binary packages supported yet.");
-                }
-                $this->pkginfo['pkgtype'] = strtolower($attribs["Type"]);
-*/
+                //if (strtolower($attribs["Type"]) != "binary") {
+                //    return $this->raiseError("Invalid package: only binary packages supported yet.");
+                //}
+                //$this->pkginfo['pkgtype'] = strtolower($attribs["Type"]);
         break;
         }
     }
@@ -446,7 +565,7 @@ class PEAR_Installer extends PEAR_Common
                 break;
         }
     }
-
+    */
     // }}}
 
     // {{{ classesDeclaredBy()