3 * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
9 * @author Stig Bakken <ssb@php.net>
10 * @author Greg Beaver <cellog@php.net>
11 * @copyright 1997-2009 The Authors
12 * @license http://opensource.org/licenses/bsd-license.php New BSD License
13 * @version CVS: $Id: Install.php 313023 2011-07-06 19:17:11Z dufuz $
14 * @link http://pear.php.net/package/PEAR
15 * @since File available since Release 0.1
21 require_once 'PEAR/Command/Common.php';
24 * PEAR commands for installation or deinstallation/upgrading of
29 * @author Stig Bakken <ssb@php.net>
30 * @author Greg Beaver <cellog@php.net>
31 * @copyright 1997-2009 The Authors
32 * @license http://opensource.org/licenses/bsd-license.php New BSD License
33 * @version Release: 1.9.4
34 * @link http://pear.php.net/package/PEAR
35 * @since Class available since Release 0.1
37 class PEAR_Command_Install extends PEAR_Command_Common
41 var $commands = array(
43 'summary' => 'Install Package',
44 'function' => 'doInstall',
49 'doc' => 'will overwrite newer installed packages',
53 'doc' => 'do not check for recommended dependency version',
57 'doc' => 'ignore dependencies, install anyway',
59 'register-only' => array(
61 'doc' => 'do not install files, only register the package as installed',
65 'doc' => 'soft install, fail silently, or upgrade if already installed',
69 'doc' => 'don\'t build C extensions',
71 'nocompress' => array(
73 'doc' => 'request uncompressed files when downloading',
75 'installroot' => array(
78 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
80 'packagingroot' => array(
83 'doc' => 'root directory used when packaging files, like RPM packaging',
85 'ignore-errors' => array(
86 'doc' => 'force install even if there were errors',
90 'doc' => 'install all required and optional dependencies',
92 'onlyreqdeps' => array(
94 'doc' => 'install all required dependencies',
98 'doc' => 'do not attempt to download any urls or contact channels',
102 'doc' => 'Only list the packages that would be downloaded',
105 'doc' => '[channel/]<package> ...
106 Installs one or more PEAR packages. You can specify a package to
107 install in four ways:
109 "Package-1.0.tgz" : installs from a local file
111 "http://example.com/Package-1.0.tgz" : installs from
114 "package.xml" : installs the package described in
115 package.xml. Useful for testing, or for wrapping a PEAR package in
116 another package manager such as RPM.
118 "Package[-version/state][.tar]" : queries your default channel\'s server
119 ({config master_server}) and downloads the newest package with
120 the preferred quality/state ({config preferred_state}).
122 To retrieve Package version 1.1, use "Package-1.1," to retrieve
123 Package state beta, use "Package-beta." To retrieve an uncompressed
124 file, append .tar (make sure there is no file by the same name first)
126 To download a package from another channel, prefix with the channel name like
129 More than one package may be specified at once. It is ok to mix these
130 four ways of specifying packages.
133 'summary' => 'Upgrade Package',
134 'function' => 'doInstall',
139 'doc' => 'upgrade packages from a specific channel',
144 'doc' => 'overwrite newer installed packages',
148 'doc' => 'do not check for recommended dependency version',
152 'doc' => 'ignore dependencies, upgrade anyway',
154 'register-only' => array(
156 'doc' => 'do not install files, only register the package as upgraded',
160 'doc' => 'don\'t build C extensions',
162 'nocompress' => array(
164 'doc' => 'request uncompressed files when downloading',
166 'installroot' => array(
169 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
171 'ignore-errors' => array(
172 'doc' => 'force install even if there were errors',
176 'doc' => 'install all required and optional dependencies',
178 'onlyreqdeps' => array(
180 'doc' => 'install all required dependencies',
184 'doc' => 'do not attempt to download any urls or contact channels',
188 'doc' => 'Only list the packages that would be downloaded',
191 'doc' => '<package> ...
192 Upgrades one or more PEAR packages. See documentation for the
193 "install" command for ways to specify a package.
195 When upgrading, your package will be updated if the provided new
196 package has a higher version number (use the -f option if you need to
199 More than one package may be specified at once.
201 'upgrade-all' => array(
202 'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
203 'function' => 'doUpgradeAll',
208 'doc' => 'upgrade packages from a specific channel',
213 'doc' => 'ignore dependencies, upgrade anyway',
215 'register-only' => array(
217 'doc' => 'do not install files, only register the package as upgraded',
221 'doc' => 'don\'t build C extensions',
223 'nocompress' => array(
225 'doc' => 'request uncompressed files when downloading',
227 'installroot' => array(
230 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
232 'ignore-errors' => array(
233 'doc' => 'force install even if there were errors',
236 'doc' => 'do not check for recommended dependency version',
240 WARNING: This function is deprecated in favor of using the upgrade command with no params
242 Upgrades all packages that have a newer release available. Upgrades are
243 done only if there is a release available of the state specified in
244 "preferred_state" (currently {config preferred_state}), or a state considered
247 'uninstall' => array(
248 'summary' => 'Un-install Package',
249 'function' => 'doUninstall',
254 'doc' => 'ignore dependencies, uninstall anyway',
256 'register-only' => array(
258 'doc' => 'do not remove files, only register the packages as not installed',
260 'installroot' => array(
263 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
265 'ignore-errors' => array(
266 'doc' => 'force install even if there were errors',
270 'doc' => 'do not attempt to uninstall remotely',
273 'doc' => '[channel/]<package> ...
274 Uninstalls one or more PEAR packages. More than one package may be
275 specified at once. Prefix with channel name to uninstall from a
276 channel not in your default channel ({config default_channel})
279 'summary' => 'Unpacks a Pecl Package',
280 'function' => 'doBundle',
283 'destination' => array(
286 'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
290 'doc' => 'Force the unpacking even if there were errors in the package',
294 Unpacks a Pecl Package into the selected location. It will download the
297 'run-scripts' => array(
298 'summary' => 'Run Post-Install Scripts bundled with a package',
299 'function' => 'doRunScripts',
304 Run post-installation scripts in package <package>, if any exist.
312 * PEAR_Command_Install constructor.
316 function PEAR_Command_Install(&$ui, &$config)
318 parent::PEAR_Command_Common($ui, $config);
324 * For unit testing purposes
326 function &getDownloader(&$ui, $options, &$config)
328 if (!class_exists('PEAR_Downloader')) {
329 require_once 'PEAR/Downloader.php';
331 $a = &new PEAR_Downloader($ui, $options, $config);
336 * For unit testing purposes
338 function &getInstaller(&$ui)
340 if (!class_exists('PEAR_Installer')) {
341 require_once 'PEAR/Installer.php';
343 $a = &new PEAR_Installer($ui);
347 function enableExtension($binaries, $type)
349 if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
350 return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
352 $ini = $this->_parseIni($phpini);
353 if (PEAR::isError($ini)) {
357 if ($type == 'extsrc' || $type == 'extbin') {
358 $search = 'extensions';
359 $enable = 'extension';
361 $search = 'zend_extensions';
363 phpinfo(INFO_GENERAL);
364 $info = ob_get_contents();
366 $debug = function_exists('leak') ? '_debug' : '';
367 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
368 $enable = 'zend_extension' . $debug . $ts;
370 foreach ($ini[$search] as $line => $extension) {
371 if (in_array($extension, $binaries, true) || in_array(
372 $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
373 // already enabled - assume if one is, all are
378 $newini = array_slice($ini['all'], 0, $line);
382 foreach ($binaries as $binary) {
383 if ($ini['extension_dir']) {
384 $binary = basename($binary);
386 $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
388 $newini = array_merge($newini, array_slice($ini['all'], $line));
389 $fp = @fopen($phpini, 'wb');
391 return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
393 foreach ($newini as $line) {
400 function disableExtension($binaries, $type)
402 if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
403 return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
405 $ini = $this->_parseIni($phpini);
406 if (PEAR::isError($ini)) {
410 if ($type == 'extsrc' || $type == 'extbin') {
411 $search = 'extensions';
412 $enable = 'extension';
414 $search = 'zend_extensions';
416 phpinfo(INFO_GENERAL);
417 $info = ob_get_contents();
419 $debug = function_exists('leak') ? '_debug' : '';
420 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
421 $enable = 'zend_extension' . $debug . $ts;
424 foreach ($ini[$search] as $line => $extension) {
425 if (in_array($extension, $binaries, true) || in_array(
426 $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
435 $fp = @fopen($phpini, 'wb');
437 return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
440 $newini = array_slice($ini['all'], 0, $line);
441 // delete the enable line
442 $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
444 $newini = array_slice($ini['all'], 1);
446 foreach ($newini as $line) {
453 function _parseIni($filename)
455 if (!file_exists($filename)) {
456 return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
459 if (filesize($filename) > 300000) {
460 return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
464 phpinfo(INFO_GENERAL);
465 $info = ob_get_contents();
467 $debug = function_exists('leak') ? '_debug' : '';
468 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
469 $zend_extension_line = 'zend_extension' . $debug . $ts;
470 $all = @file($filename);
472 return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
474 $zend_extensions = $extensions = array();
475 // assume this is right, but pull from the php.ini if it is found
476 $extension_dir = ini_get('extension_dir');
477 foreach ($all as $linenum => $line) {
482 if ($line[0] == ';') {
485 if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
486 $line = trim(substr($line, 13));
487 if ($line[0] == '=') {
488 $x = trim(substr($line, 1));
489 $x = explode(';', $x);
490 $extension_dir = str_replace('"', '', array_shift($x));
494 if (strtolower(substr($line, 0, 9)) == 'extension') {
495 $line = trim(substr($line, 9));
496 if ($line[0] == '=') {
497 $x = trim(substr($line, 1));
498 $x = explode(';', $x);
499 $extensions[$linenum] = str_replace('"', '', array_shift($x));
503 if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
504 $zend_extension_line) {
505 $line = trim(substr($line, strlen($zend_extension_line)));
506 if ($line[0] == '=') {
507 $x = trim(substr($line, 1));
508 $x = explode(';', $x);
509 $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
515 'extensions' => $extensions,
516 'zend_extensions' => $zend_extensions,
517 'extension_dir' => $extension_dir,
524 function doInstall($command, $options, $params)
526 if (!class_exists('PEAR_PackageFile')) {
527 require_once 'PEAR/PackageFile.php';
530 if (isset($options['installroot']) && isset($options['packagingroot'])) {
531 return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
534 $reg = &$this->config->getRegistry();
535 $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
536 if (!$reg->channelExists($channel)) {
537 return $this->raiseError('Channel "' . $channel . '" does not exist');
540 if (empty($this->installer)) {
541 $this->installer = &$this->getInstaller($this->ui);
544 if ($command == 'upgrade' || $command == 'upgrade-all') {
545 // If people run the upgrade command but pass nothing, emulate a upgrade-all
546 if ($command == 'upgrade' && empty($params)) {
547 return $this->doUpgradeAll($command, $options, $params);
549 $options['upgrade'] = true;
554 $instreg = &$reg; // instreg used to check if package is installed
555 if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
556 $packrootphp_dir = $this->installer->_prependPath(
557 $this->config->get('php_dir', null, 'pear.php.net'),
558 $options['packagingroot']);
559 $instreg = new PEAR_Registry($packrootphp_dir); // other instreg!
561 if ($this->config->get('verbose') > 2) {
562 $this->ui->outputData('using package root: ' . $options['packagingroot']);
566 $abstractpackages = $otherpackages = array();
568 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
570 foreach ($params as $param) {
571 if (strpos($param, 'http://') === 0) {
572 $otherpackages[] = $param;
576 if (strpos($param, 'channel://') === false && @file_exists($param)) {
577 if (isset($options['force'])) {
578 $otherpackages[] = $param;
582 $pkg = new PEAR_PackageFile($this->config);
583 $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
584 if (PEAR::isError($pf)) {
585 $otherpackages[] = $param;
589 $exists = $reg->packageExists($pf->getPackage(), $pf->getChannel());
590 $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
591 $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
592 if ($exists && $version_compare) {
593 if ($this->config->get('verbose')) {
594 $this->ui->outputData('Ignoring installed package ' .
595 $reg->parsedPackageNameToString(
596 array('package' => $pf->getPackage(),
597 'channel' => $pf->getChannel()), true));
601 $otherpackages[] = $param;
605 $e = $reg->parsePackageName($param, $channel);
606 if (PEAR::isError($e)) {
607 $otherpackages[] = $param;
609 $abstractpackages[] = $e;
612 PEAR::staticPopErrorHandling();
614 // if there are any local package .tgz or remote static url, we can't
615 // filter. The filter only works for abstract packages
616 if (count($abstractpackages) && !isset($options['force'])) {
617 // when not being forced, only do necessary upgrades/installs
618 if (isset($options['upgrade'])) {
619 $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
621 $count = count($abstractpackages);
622 foreach ($abstractpackages as $i => $package) {
623 if (isset($package['group'])) {
624 // do not filter out install groups
628 if ($instreg->packageExists($package['package'], $package['channel'])) {
630 if ($this->config->get('verbose')) {
631 $this->ui->outputData('Ignoring installed package ' .
632 $reg->parsedPackageNameToString($package, true));
634 unset($abstractpackages[$i]);
635 } elseif ($count === 1) {
636 // Lets try to upgrade it since it's already installed
637 $options['upgrade'] = true;
643 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
644 } elseif (count($abstractpackages)) {
646 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
649 $packages = array_merge($abstractpackages, $otherpackages);
650 if (!count($packages)) {
652 if (isset($options['channel'])){
653 $c .= ' in channel "' . $options['channel'] . '"';
655 $this->ui->outputData('Nothing to ' . $command . $c);
659 $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
660 $errors = $downloaded = $binaries = array();
661 $downloaded = &$this->downloader->download($packages);
662 if (PEAR::isError($downloaded)) {
663 return $this->raiseError($downloaded);
666 $errors = $this->downloader->getErrorMsgs();
667 if (count($errors)) {
669 $err['data'] = array();
670 foreach ($errors as $error) {
671 if ($error !== null) {
672 $err['data'][] = array($error);
676 if (!empty($err['data'])) {
677 $err['headline'] = 'Install Errors';
678 $this->ui->outputData($err);
681 if (!count($downloaded)) {
682 return $this->raiseError("$command failed");
687 'headline' => 'Packages that would be Installed'
690 if (isset($options['pretend'])) {
691 foreach ($downloaded as $package) {
692 $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
694 $this->ui->outputData($data, 'pretend');
698 $this->installer->setOptions($options);
699 $this->installer->sortPackagesForInstall($downloaded);
700 if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
701 $this->raiseError($err->getMessage());
705 $binaries = $extrainfo = array();
706 foreach ($downloaded as $param) {
707 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
708 $info = $this->installer->install($param, $options);
709 PEAR::staticPopErrorHandling();
710 if (PEAR::isError($info)) {
712 $pkg = &$param->getPackageFile();
713 if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
714 if (!($info = $pkg->installBinary($this->installer))) {
715 $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
719 // we just installed a different package than requested,
720 // let's change the param and info so that the rest of this works
726 if (!is_array($info)) {
727 return $this->raiseError("$command failed");
730 if ($param->getPackageType() == 'extsrc' ||
731 $param->getPackageType() == 'extbin' ||
732 $param->getPackageType() == 'zendextsrc' ||
733 $param->getPackageType() == 'zendextbin'
735 $pkg = &$param->getPackageFile();
736 if ($instbin = $pkg->getInstalledBinary()) {
737 $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
739 $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
742 foreach ($instpkg->getFilelist() as $name => $atts) {
743 $pinfo = pathinfo($atts['installed_as']);
744 if (!isset($pinfo['extension']) ||
745 in_array($pinfo['extension'], array('c', 'h'))
747 continue; // make sure we don't match php_blah.h
750 if ((strpos($pinfo['basename'], 'php_') === 0 &&
751 $pinfo['extension'] == 'dll') ||
753 $pinfo['extension'] == 'so' ||
755 $pinfo['extension'] == 'sl') {
756 $binaries[] = array($atts['installed_as'], $pinfo);
761 if (count($binaries)) {
762 foreach ($binaries as $pinfo) {
763 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
764 $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
765 PEAR::staticPopErrorHandling();
766 if (PEAR::isError($ret)) {
767 $extrainfo[] = $ret->getMessage();
768 if ($param->getPackageType() == 'extsrc' ||
769 $param->getPackageType() == 'extbin') {
770 $exttype = 'extension';
773 phpinfo(INFO_GENERAL);
774 $info = ob_get_contents();
776 $debug = function_exists('leak') ? '_debug' : '';
777 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
778 $exttype = 'zend_extension' . $debug . $ts;
780 $extrainfo[] = 'You should add "' . $exttype . '=' .
781 $pinfo[1]['basename'] . '" to php.ini';
783 $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
784 ' enabled in php.ini';
790 if ($this->config->get('verbose') > 0) {
791 $chan = $param->getChannel();
792 $label = $reg->parsedPackageNameToString(
795 'package' => $param->getPackage(),
796 'version' => $param->getVersion(),
798 $out = array('data' => "$command ok: $label");
799 if (isset($info['release_warnings'])) {
800 $out['release_warnings'] = $info['release_warnings'];
802 $this->ui->outputData($out, $command);
804 if (!isset($options['register-only']) && !isset($options['offline'])) {
805 if ($this->config->isDefinedLayer('ftp')) {
806 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
807 $info = $this->installer->ftpInstall($param);
808 PEAR::staticPopErrorHandling();
809 if (PEAR::isError($info)) {
810 $this->ui->outputData($info->getMessage());
811 $this->ui->outputData("remote install failed: $label");
813 $this->ui->outputData("remote install ok: $label");
819 $deps = $param->getDeps();
821 if (isset($deps['group'])) {
822 $groups = $deps['group'];
823 if (!isset($groups[0])) {
824 $groups = array($groups);
827 foreach ($groups as $group) {
828 if ($group['attribs']['name'] == 'default') {
829 // default group is always installed, unless the user
830 // explicitly chooses to install another group
833 $extrainfo[] = $param->getPackage() . ': Optional feature ' .
834 $group['attribs']['name'] . ' available (' .
835 $group['attribs']['hint'] . ')';
838 $extrainfo[] = $param->getPackage() .
839 ': To install optional features use "pear install ' .
840 $reg->parsedPackageNameToString(
841 array('package' => $param->getPackage(),
842 'channel' => $param->getChannel()), true) .
847 $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
848 // $pkg may be NULL if install is a 'fake' install via --packagingroot
849 if (is_object($pkg)) {
850 $pkg->setConfig($this->config);
851 if ($list = $pkg->listPostinstallScripts()) {
852 $pn = $reg->parsedPackageNameToString(array('channel' =>
853 $param->getChannel(), 'package' => $param->getPackage()), true);
854 $extrainfo[] = $pn . ' has post-install scripts:';
855 foreach ($list as $file) {
856 $extrainfo[] = $file;
858 $extrainfo[] = $param->getPackage() .
859 ': Use "pear run-scripts ' . $pn . '" to finish setup.';
860 $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
865 if (count($extrainfo)) {
866 foreach ($extrainfo as $info) {
867 $this->ui->outputData($info);
875 // {{{ doUpgradeAll()
877 function doUpgradeAll($command, $options, $params)
879 $reg = &$this->config->getRegistry();
882 if (isset($options['channel'])) {
883 $channels = array($options['channel']);
885 $channels = $reg->listChannels();
888 foreach ($channels as $channel) {
889 if ($channel == '__uri') {
893 // parse name with channel
894 foreach ($reg->listPackages($channel) as $name) {
895 $upgrade[] = $reg->parsedPackageNameToString(array(
896 'channel' => $channel,
902 $err = $this->doInstall($command, $options, $upgrade);
903 if (PEAR::isError($err)) {
904 $this->ui->outputData($err->getMessage(), $command);
911 function doUninstall($command, $options, $params)
913 if (count($params) < 1) {
914 return $this->raiseError("Please supply the package(s) you want to uninstall");
917 if (empty($this->installer)) {
918 $this->installer = &$this->getInstaller($this->ui);
921 if (isset($options['remoteconfig'])) {
922 $e = $this->config->readFTPConfigFile($options['remoteconfig']);
923 if (!PEAR::isError($e)) {
924 $this->installer->setConfig($this->config);
928 $reg = &$this->config->getRegistry();
929 $newparams = array();
931 $badparams = array();
932 foreach ($params as $pkg) {
933 $channel = $this->config->get('default_channel');
934 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
935 $parsed = $reg->parsePackageName($pkg, $channel);
936 PEAR::staticPopErrorHandling();
937 if (!$parsed || PEAR::isError($parsed)) {
941 $package = $parsed['package'];
942 $channel = $parsed['channel'];
943 $info = &$reg->getPackage($package, $channel);
944 if ($info === null &&
945 ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
946 // make sure this isn't a package that has flipped from pear to pecl but
947 // used a package.xml 1.0
948 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
949 $info = &$reg->getPackage($package, $testc);
950 if ($info !== null) {
954 if ($info === null) {
957 $newparams[] = &$info;
958 // check for binary packages (this is an alias for those packages if so)
959 if ($installedbinary = $info->getInstalledBinary()) {
960 $this->ui->log('adding binary package ' .
961 $reg->parsedPackageNameToString(array('channel' => $channel,
962 'package' => $installedbinary), true));
963 $newparams[] = &$reg->getPackage($installedbinary, $channel);
965 // add the contents of a dependency group to the list of installed packages
966 if (isset($parsed['group'])) {
967 $group = $info->getDependencyGroup($parsed['group']);
969 $installed = $reg->getInstalledGroup($group);
971 foreach ($installed as $i => $p) {
972 $newparams[] = &$installed[$i];
979 $err = $this->installer->sortPackagesForUninstall($newparams);
980 if (PEAR::isError($err)) {
981 $this->ui->outputData($err->getMessage(), $command);
984 $params = $newparams;
985 // twist this to use it to check on whether dependent packages are also being uninstalled
986 // for circular dependencies like subpackages
987 $this->installer->setUninstallPackages($newparams);
988 $params = array_merge($params, $badparams);
990 foreach ($params as $pkg) {
991 $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
992 if ($err = $this->installer->uninstall($pkg, $options)) {
993 $this->installer->popErrorHandling();
994 if (PEAR::isError($err)) {
995 $this->ui->outputData($err->getMessage(), $command);
998 if ($pkg->getPackageType() == 'extsrc' ||
999 $pkg->getPackageType() == 'extbin' ||
1000 $pkg->getPackageType() == 'zendextsrc' ||
1001 $pkg->getPackageType() == 'zendextbin') {
1002 if ($instbin = $pkg->getInstalledBinary()) {
1003 continue; // this will be uninstalled later
1006 foreach ($pkg->getFilelist() as $name => $atts) {
1007 $pinfo = pathinfo($atts['installed_as']);
1008 if (!isset($pinfo['extension']) ||
1009 in_array($pinfo['extension'], array('c', 'h'))) {
1010 continue; // make sure we don't match php_blah.h
1012 if ((strpos($pinfo['basename'], 'php_') === 0 &&
1013 $pinfo['extension'] == 'dll') ||
1015 $pinfo['extension'] == 'so' ||
1017 $pinfo['extension'] == 'sl') {
1018 $binaries[] = array($atts['installed_as'], $pinfo);
1022 if (count($binaries)) {
1023 foreach ($binaries as $pinfo) {
1024 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1025 $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
1026 PEAR::staticPopErrorHandling();
1027 if (PEAR::isError($ret)) {
1028 $extrainfo[] = $ret->getMessage();
1029 if ($pkg->getPackageType() == 'extsrc' ||
1030 $pkg->getPackageType() == 'extbin') {
1031 $exttype = 'extension';
1034 phpinfo(INFO_GENERAL);
1035 $info = ob_get_contents();
1037 $debug = function_exists('leak') ? '_debug' : '';
1038 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
1039 $exttype = 'zend_extension' . $debug . $ts;
1041 $this->ui->outputData('Unable to remove "' . $exttype . '=' .
1042 $pinfo[1]['basename'] . '" from php.ini', $command);
1044 $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
1045 ' disabled in php.ini', $command);
1051 if ($this->config->get('verbose') > 0) {
1052 if (is_object($pkg)) {
1053 $pkg = $reg->parsedPackageNameToString($pkg);
1055 $this->ui->outputData("uninstall ok: $pkg", $command);
1057 if (!isset($options['offline']) && is_object($savepkg) &&
1058 defined('PEAR_REMOTEINSTALL_OK')) {
1059 if ($this->config->isDefinedLayer('ftp')) {
1060 $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
1061 $info = $this->installer->ftpUninstall($savepkg);
1062 $this->installer->popErrorHandling();
1063 if (PEAR::isError($info)) {
1064 $this->ui->outputData($info->getMessage());
1065 $this->ui->outputData("remote uninstall failed: $pkg");
1067 $this->ui->outputData("remote uninstall ok: $pkg");
1072 $this->installer->popErrorHandling();
1073 if (!is_object($pkg)) {
1074 return $this->raiseError("uninstall failed: $pkg");
1076 $pkg = $reg->parsedPackageNameToString($pkg);
1089 (cox) It just downloads and untars the package, does not do
1090 any check that the PEAR_Installer::_installFile() does.
1093 function doBundle($command, $options, $params)
1099 'downloadonly' => true
1101 $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
1102 $reg = &$this->config->getRegistry();
1103 if (count($params) < 1) {
1104 return $this->raiseError("Please supply the package you want to bundle");
1107 if (isset($options['destination'])) {
1108 if (!is_dir($options['destination'])) {
1109 System::mkdir('-p ' . $options['destination']);
1111 $dest = realpath($options['destination']);
1114 $dir = $pwd . DIRECTORY_SEPARATOR . 'ext';
1115 $dest = is_dir($dir) ? $dir : $pwd;
1117 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1118 $err = $downloader->setDownloadDir($dest);
1119 PEAR::staticPopErrorHandling();
1120 if (PEAR::isError($err)) {
1121 return PEAR::raiseError('download directory "' . $dest .
1122 '" is not writeable.');
1124 $result = &$downloader->download(array($params[0]));
1125 if (PEAR::isError($result)) {
1128 if (!isset($result[0])) {
1129 return $this->raiseError('unable to unpack ' . $params[0]);
1131 $pkgfile = &$result[0]->getPackageFile();
1132 $pkgname = $pkgfile->getName();
1133 $pkgversion = $pkgfile->getVersion();
1135 // Unpacking -------------------------------------------------
1136 $dest .= DIRECTORY_SEPARATOR . $pkgname;
1137 $orig = $pkgname . '-' . $pkgversion;
1139 $tar = &new Archive_Tar($pkgfile->getArchiveFile());
1140 if (!$tar->extractModify($dest, $orig)) {
1141 return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
1143 $this->ui->outputData("Package ready at '$dest'");
1149 function doRunScripts($command, $options, $params)
1151 if (!isset($params[0])) {
1152 return $this->raiseError('run-scripts expects 1 parameter: a package name');
1155 $reg = &$this->config->getRegistry();
1156 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1157 $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
1158 PEAR::staticPopErrorHandling();
1159 if (PEAR::isError($parsed)) {
1160 return $this->raiseError($parsed);
1163 $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
1164 if (!is_object($package)) {
1165 return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
1168 $package->setConfig($this->config);
1169 $package->runPostinstallScripts();
1170 $this->ui->outputData('Install scripts complete', $command);
1175 * Given a list of packages, filter out those ones that are already up to date
1177 * @param $packages: packages, in parsed array format !
1178 * @return list of packages that can be upgraded
1180 function _filterUptodatePackages($packages, $command)
1182 $reg = &$this->config->getRegistry();
1183 $latestReleases = array();
1186 foreach ($packages as $package) {
1187 if (isset($package['group'])) {
1192 $channel = $package['channel'];
1193 $name = $package['package'];
1194 if (!$reg->packageExists($name, $channel)) {
1199 if (!isset($latestReleases[$channel])) {
1200 // fill in cache for this channel
1201 $chan = &$reg->getChannel($channel);
1202 if (PEAR::isError($chan)) {
1203 return $this->raiseError($chan);
1207 $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
1208 if ($chan->supportsREST($preferred_mirror) &&
1210 //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
1211 ($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
1217 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1218 if (!isset($package['state'])) {
1219 $state = $this->config->get('preferred_state', null, $channel);
1221 $state = $package['state'];
1226 $rest = &$this->config->getREST('1.4', array());
1229 $rest = &$this->config->getREST('1.0', array());
1232 $installed = array_flip($reg->listPackages($channel));
1233 $latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
1236 PEAR::staticPopErrorHandling();
1237 if (PEAR::isError($latest)) {
1238 $this->ui->outputData('Error getting channel info from ' . $channel .
1239 ': ' . $latest->getMessage());
1243 $latestReleases[$channel] = array_change_key_case($latest);
1246 // check package for latest release
1247 $name_lower = strtolower($name);
1248 if (isset($latestReleases[$channel][$name_lower])) {
1249 // if not set, up to date
1250 $inst_version = $reg->packageInfo($name, 'version', $channel);
1251 $channel_version = $latestReleases[$channel][$name_lower]['version'];
1252 if (version_compare($channel_version, $inst_version, 'le')) {
1253 // installed version is up-to-date
1258 if ($command == 'upgrade-all') {
1259 $this->ui->outputData(array('data' => 'Will upgrade ' .
1260 $reg->parsedPackageNameToString($package)), $command);