Пример #1
0
 /**
  * @static
  * @final
  */
 function runPostinstallTasks()
 {
     foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
         $err = call_user_func(array($class, 'run'), $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]);
         if ($err) {
             return PEAR_Task_Common::throwError($err);
         }
     }
     unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
 }
Пример #2
0
 /**
  * Installs the files within the package file specified.
  *
  * @param string|PEAR_Downloader_Package $pkgfile path to the package file,
  *        or a pre-initialized packagefile object
  * @param array $options
  * recognized options:
  * - installroot   : optional prefix directory for installation
  * - force         : force installation
  * - register-only : update registry but don't install files
  * - upgrade       : upgrade existing install
  * - soft          : fail silently
  * - nodeps        : ignore dependency conflicts/missing dependencies
  * - alldeps       : install all dependencies
  * - onlyreqdeps   : install only required dependencies
  *
  * @return array|PEAR_Error package info if successful
  */
 function install($pkgfile, $options = array())
 {
     $this->_options = $options;
     $this->_registry =& $this->config->getRegistry();
     if (is_object($pkgfile)) {
         $dlpkg =& $pkgfile;
         $pkg = $pkgfile->getPackageFile();
         $pkgfile = $pkg->getArchiveFile();
         $descfile = $pkg->getPackageFile();
         $tmpdir = dirname($descfile);
     } else {
         $descfile = $pkgfile;
         $tmpdir = '';
         if (PEAR::isError($pkg =& $this->_parsePackageXml($descfile, $tmpdir))) {
             return $pkg;
         }
     }
     if (realpath($descfile) != realpath($pkgfile)) {
         $tar = new Archive_Tar($pkgfile);
         if (!@$tar->extract($tmpdir)) {
             return $this->raiseError("unable to unpack {$pkgfile}");
         }
     }
     $pkgname = $pkg->getName();
     $channel = $pkg->getChannel();
     if (isset($this->_options['packagingroot'])) {
         $packrootphp_dir = $this->_prependPath($this->config->get('php_dir', null, $channel), $this->_options['packagingroot']);
     }
     if (isset($options['installroot'])) {
         $this->config->setInstallRoot($options['installroot']);
         $this->_registry =& $this->config->getRegistry();
         $installregistry =& $this->_registry;
         $this->installroot = '';
         // all done automagically now
         $php_dir = $this->config->get('php_dir', null, $channel);
     } else {
         $this->config->setInstallRoot(false);
         $this->_registry =& $this->config->getRegistry();
         if (isset($this->_options['packagingroot'])) {
             $installregistry =& new PEAR_Registry($packrootphp_dir);
             $php_dir = $packrootphp_dir;
         } else {
             $installregistry =& $this->_registry;
             $php_dir = $this->config->get('php_dir', null, $channel);
         }
         $this->installroot = '';
     }
     // {{{ checks to do when not in "force" mode
     if (empty($options['force']) && @is_dir($this->config->get('php_dir'))) {
         $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
         $instfilelist = $pkg->getInstallationFileList(true);
         if (PEAR::isError($instfilelist)) {
             return $instfilelist;
         }
         $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
         if (PEAR::isError($test)) {
             return $test;
         }
         if (sizeof($test)) {
             $pkgs = $this->getInstallPackages();
             $found = false;
             foreach ($pkgs as $param) {
                 if ($pkg->isSubpackageOf($param)) {
                     $found = true;
                     break;
                 }
             }
             if ($found) {
                 // subpackages can conflict with earlier versions of parent packages
                 $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
                 $tmp = $test;
                 foreach ($tmp as $file => $info) {
                     if (is_array($info)) {
                         if (strtolower($info[1]) == strtolower($param->getPackage()) && strtolower($info[0]) == strtolower($param->getChannel())) {
                             unset($test[$file]);
                             unset($parentreg['filelist'][$file]);
                         }
                     } else {
                         if (strtolower($param->getChannel()) != 'pear.php.net') {
                             continue;
                         }
                         if (strtolower($info) == strtolower($param->getPackage())) {
                             unset($test[$file]);
                             unset($parentreg['filelist'][$file]);
                         }
                     }
                 }
                 $pfk =& new PEAR_PackageFile($this->config);
                 $parentpkg =& $pfk->fromArray($parentreg);
                 $installregistry->updatePackage2($parentpkg);
             }
             if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
                 $tmp = $test;
                 foreach ($tmp as $file => $info) {
                     if (is_string($info)) {
                         // pear.php.net packages are always stored as strings
                         if (strtolower($info) == strtolower($param->getPackage())) {
                             // upgrading existing package
                             unset($test[$file]);
                         }
                     }
                 }
             }
             if (sizeof($test)) {
                 $msg = "{$channel}/{$pkgname}: conflicting files found:\n";
                 $longest = max(array_map("strlen", array_keys($test)));
                 $fmt = "%{$longest}s (%s)\n";
                 foreach ($test as $file => $info) {
                     if (!is_array($info)) {
                         $info = array('pear.php.net', $info);
                     }
                     $info = $info[0] . '/' . $info[1];
                     $msg .= sprintf($fmt, $file, $info);
                 }
                 if (!isset($options['ignore-errors'])) {
                     return $this->raiseError($msg);
                 } else {
                     if (!isset($options['soft'])) {
                         $this->log(0, "WARNING: {$msg}");
                     }
                 }
             }
         }
     }
     // }}}
     $this->startFileTransaction();
     if (empty($options['upgrade']) && empty($options['soft'])) {
         // checks to do only when installing new packages
         if ($channel == 'pecl.php.net') {
             $test = $installregistry->packageExists($pkgname, $channel);
             if (!$test) {
                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
             }
         } else {
             $test = $installregistry->packageExists($pkgname, $channel);
         }
         if (empty($options['force']) && $test) {
             return $this->raiseError("{$channel}/{$pkgname} is already installed");
         }
     } else {
         $usechannel = $channel;
         if ($channel == 'pecl.php.net') {
             $test = $installregistry->packageExists($pkgname, $channel);
             if (!$test) {
                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                 $usechannel = 'pear.php.net';
             }
         } else {
             $test = $installregistry->packageExists($pkgname, $channel);
         }
         if ($test) {
             $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
             $v2 = $pkg->getVersion();
             $cmp = version_compare("{$v1}", "{$v2}", 'gt');
             if (empty($options['force']) && !version_compare("{$v2}", "{$v1}", 'gt')) {
                 return $this->raiseError("upgrade to a newer version ({$v2} is not newer than {$v1})");
             }
             if (empty($options['register-only'])) {
                 // when upgrading, remove old release's files first:
                 if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel, true))) {
                     if (!isset($options['ignore-errors'])) {
                         return $this->raiseError($err);
                     } else {
                         if (!isset($options['soft'])) {
                             $this->log(0, 'WARNING: ' . $err->getMessage());
                         }
                     }
                 } else {
                     $backedup = $err;
                 }
             }
         }
     }
     // {{{ Copy files to dest dir ---------------------------------------
     // info from the package it self we want to access from _installFile
     $this->pkginfo =& $pkg;
     // used to determine whether we should build any C code
     $this->source_files = 0;
     $savechannel = $this->config->get('default_channel');
     if (empty($options['register-only']) && !is_dir($php_dir)) {
         if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
             return $this->raiseError("no installation destination directory '{$php_dir}'\n");
         }
     }
     $tmp_path = dirname($descfile);
     if (substr($pkgfile, -4) != '.xml') {
         $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
     }
     $this->configSet('default_channel', $channel);
     // {{{ install files
     if ($pkg->getPackagexmlVersion() == '2.0') {
         $filelist = $pkg->getInstallationFilelist();
     } else {
         $filelist = $pkg->getFileList();
     }
     if (PEAR::isError($filelist)) {
         return $filelist;
     }
     $pkg->resetFilelist();
     $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), 'version', $pkg->getChannel()));
     foreach ($filelist as $file => $atts) {
         if ($pkg->getPackagexmlVersion() == '1.0') {
             $this->expectError(PEAR_INSTALLER_FAILED);
             $res = $this->_installFile($file, $atts, $tmp_path, $options);
             $this->popExpect();
         } else {
             $this->expectError(PEAR_INSTALLER_FAILED);
             $res = $this->_installFile2($pkg, $file, $atts, $tmp_path, $options);
             $this->popExpect();
         }
         if (PEAR::isError($res)) {
             if (empty($options['ignore-errors'])) {
                 $this->rollbackFileTransaction();
                 if ($res->getMessage() == "file does not exist") {
                     $this->raiseError("file {$file} in package.xml does not exist");
                 }
                 return $this->raiseError($res);
             } else {
                 if (!isset($options['soft'])) {
                     $this->log(0, "Warning: " . $res->getMessage());
                 }
             }
         }
         if ($res == PEAR_INSTALLER_OK) {
             // Register files that were installed
             $pkg->installedFile($file, $atts);
         }
     }
     // }}}
     // {{{ compile and install source files
     if ($this->source_files > 0 && empty($options['nobuild'])) {
         if (PEAR::isError($err = $this->_compileSourceFiles($savechannel, $pkg))) {
             return $err;
         }
     }
     // }}}
     if (isset($backedup)) {
         $this->_removeBackups($backedup);
     }
     if (!$this->commitFileTransaction()) {
         $this->rollbackFileTransaction();
         $this->configSet('default_channel', $savechannel);
         return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
     }
     // }}}
     $ret = false;
     $installphase = 'install';
     $oldversion = false;
     // {{{ Register that the package is installed -----------------------
     if (empty($options['upgrade'])) {
         // if 'force' is used, replace the info in registry
         $usechannel = $channel;
         if ($channel == 'pecl.php.net') {
             $test = $installregistry->packageExists($pkgname, $channel);
             if (!$test) {
                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                 $usechannel = 'pear.php.net';
             }
         } else {
             $test = $installregistry->packageExists($pkgname, $channel);
         }
         if (!empty($options['force']) && $test) {
             $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
             $installregistry->deletePackage($pkgname, $usechannel);
         }
         $ret = $installregistry->addPackage2($pkg);
     } else {
         $usechannel = $channel;
         if ($channel == 'pecl.php.net') {
             $test = $installregistry->packageExists($pkgname, $channel);
             if (!$test) {
                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                 $usechannel = 'pear.php.net';
             }
         } else {
             $test = $installregistry->packageExists($pkgname, $channel);
         }
         // new: upgrade installs a package if it isn't installed
         if (!$test) {
             $ret = $installregistry->addPackage2($pkg);
         } else {
             if ($usechannel != $channel) {
                 $installregistry->deletePackage($pkgname, $usechannel);
                 $ret = $installregistry->addPackage2($pkg);
             } else {
                 $ret = $installregistry->updatePackage2($pkg);
             }
             $installphase = 'upgrade';
         }
     }
     if (!$ret) {
         $this->configSet('default_channel', $savechannel);
         return $this->raiseError("Adding package {$channel}/{$pkgname} to registry failed");
     }
     // }}}
     $this->configSet('default_channel', $savechannel);
     if (class_exists('PEAR_Task_Common')) {
         // this is auto-included if any tasks exist
         if (PEAR_Task_Common::hasPostinstallTasks()) {
             PEAR_Task_Common::runPostinstallTasks($installphase);
         }
     }
     return $pkg->toArray(true);
 }