function isInstalled($dep, $oper = '==') { if (!$dep) { return false; } if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') { return false; } if (is_object($dep)) { $package = $dep->getPackage(); $channel = $dep->getChannel(); if ($dep->getURI()) { $dep = array('uri' => $dep->getURI(), 'version' => $dep->getVersion()); } else { $dep = array('version' => $dep->getVersion()); } } else { if (isset($dep['uri'])) { $channel = '__uri'; $package = $dep['dep']['name']; } else { $channel = $dep['info']->getChannel(); $package = $dep['info']->getPackage(); } } $options = $this->_downloader->getOptions(); $test = $this->_registry->packageExists($package, $channel); if (!$test && $channel == 'pecl.php.net') { // do magic to allow upgrading from old pecl packages to new ones $test = $this->_registry->packageExists($package, 'pear.php.net'); $channel = 'pear.php.net'; } if ($test) { if (isset($dep['uri'])) { if ($this->_registry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { return true; } } if (isset($options['upgrade'])) { if ($oper == 'has') { if (version_compare($this->_registry->packageInfo($package, 'version', $channel), $dep['version'], '>=')) { return true; } else { return false; } } else { if (version_compare($this->_registry->packageInfo($package, 'version', $channel), $dep['version'], '>=')) { return true; } return false; } } return true; } return false; }
$ch_cmd =& PEAR_Command::factory('update-channels', $config); $ch_cmd->run('update-channels', $options, array()); PEAR::staticPopErrorHandling(); // reset error handling unset($ch_cmd); print "\n" . 'Installing selected packages..................' . "\n"; displayHTMLProgress($progress = 45); $install =& PEAR_Command::factory('install', $config); foreach ($to_install as $pkg) { $pkg_basename = substr($pkg, 0, strpos($pkg, '-')); if (in_array($pkg, $installer_packages)) { $options = array('nodeps' => true); } else { $options = array('onlyreqdeps' => true); } if ($registry->packageExists($pkg) || $registry->packageExists($pkg_basename)) { print str_pad("Package: {$pkg}", max(50, 9 + strlen($pkg) + 4), '.') . ' already installed ... ok' . "\n"; displayHTMLProgress($progress += round(50 / count($to_install))); continue; } $pkg_basename = substr($pkg, 0, strpos($pkg, '-')); if (in_array($pkg_basename, $bootstrap_pkgs)) { print str_pad("Installing bootstrap package: {$pkg_basename}", max(50, 30 + strlen($pkg_basename) + 4), '.') . "..."; displayHTMLProgress($progress += round(25 / count($to_install))); $install->run('install', $options, array($bootstrap_pkgs_tarballs[$pkg_basename])); } elseif (isset($local_dir[$pkg_basename])) { print str_pad("Installing local package: {$pkg}", max(50, 26 + strlen($pkg) + 4), '.') . "..."; displayHTMLProgress($progress += round(25 / count($to_install))); $install->run('install', $options, array($gopear_bundle_dir . '/' . $local_dir[$pkg_basename])); } else { // no local copy
function doInstall($command, $options, $params) { if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } if (empty($this->installer)) { $this->installer =& $this->getInstaller($this->ui); } if ($command == 'upgrade' || $command == 'upgrade-all') { $options['upgrade'] = true; } else { $packages = $params; } if (isset($options['installroot']) && isset($options['packagingroot'])) { return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot'); } $reg =& $this->config->getRegistry(); $instreg =& $reg; // instreg used to check if package is installed if (isset($options['packagingroot']) && !isset($options['upgrade'])) { $packrootphp_dir = $this->installer->_prependPath($this->config->get('php_dir', null, 'pear.php.net'), $options['packagingroot']); $instreg = new PEAR_Registry($packrootphp_dir); // other instreg! if ($this->config->get('verbose') > 2) { $this->ui->outputData('using package root: ' . $options['packagingroot']); } } $abstractpackages = array(); $otherpackages = array(); // parse params PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); foreach ($params as $param) { if (strpos($param, 'http://') === 0) { $otherpackages[] = $param; continue; } if (strpos($param, 'channel://') === false && @file_exists($param)) { if (isset($options['force'])) { $otherpackages[] = $param; continue; } $pkg = new PEAR_PackageFile($this->config); $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING); if (PEAR::isError($pf)) { $otherpackages[] = $param; continue; } if ($reg->packageExists($pf->getPackage(), $pf->getChannel()) && version_compare($pf->getVersion(), $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel()), '<=')) { if ($this->config->get('verbose')) { $this->ui->outputData('Ignoring installed package ' . $reg->parsedPackageNameToString(array('package' => $pf->getPackage(), 'channel' => $pf->getChannel()), true)); } continue; } $otherpackages[] = $param; continue; } $e = $reg->parsePackageName($param, $this->config->get('default_channel')); if (PEAR::isError($e)) { $otherpackages[] = $param; } else { $abstractpackages[] = $e; } } PEAR::staticPopErrorHandling(); // if there are any local package .tgz or remote static url, we can't // filter. The filter only works for abstract packages if (count($abstractpackages) && !isset($options['force'])) { // when not being forced, only do necessary upgrades/installs if (isset($options['upgrade'])) { $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command); } else { foreach ($abstractpackages as $i => $package) { if (isset($package['group'])) { // do not filter out install groups continue; } if ($instreg->packageExists($package['package'], $package['channel'])) { if ($this->config->get('verbose')) { $this->ui->outputData('Ignoring installed package ' . $reg->parsedPackageNameToString($package, true)); } unset($abstractpackages[$i]); } } } $abstractpackages = array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); } elseif (count($abstractpackages)) { $abstractpackages = array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); } $packages = array_merge($abstractpackages, $otherpackages); if (!count($packages)) { $this->ui->outputData('Nothing to ' . $command); return true; } $this->downloader =& $this->getDownloader($this->ui, $options, $this->config); $errors = array(); $binaries = array(); $downloaded = array(); $downloaded =& $this->downloader->download($packages); if (PEAR::isError($downloaded)) { return $this->raiseError($downloaded); } $errors = $this->downloader->getErrorMsgs(); if (count($errors)) { $err = array(); $err['data'] = array(); foreach ($errors as $error) { $err['data'][] = array($error); } $err['headline'] = 'Install Errors'; $this->ui->outputData($err); if (!count($downloaded)) { return $this->raiseError("{$command} failed"); } } $data = array('headline' => 'Packages that would be Installed'); if (isset($options['pretend'])) { foreach ($downloaded as $package) { $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage())); } $this->ui->outputData($data, 'pretend'); return true; } $this->installer->setOptions($options); $this->installer->sortPackagesForInstall($downloaded); if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) { $this->raiseError($err->getMessage()); return true; } $extrainfo = array(); $binaries = array(); foreach ($downloaded as $param) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->install($param, $options); PEAR::staticPopErrorHandling(); if (PEAR::isError($info)) { $oldinfo = $info; $pkg =& $param->getPackageFile(); if ($info->getCode() != PEAR_INSTALLER_NOBINARY) { if (!($info = $pkg->installBinary($this->installer))) { $this->ui->outputData('ERROR: ' . $oldinfo->getMessage()); continue; } // we just installed a different package than requested, // let's change the param and info so that the rest of this works $param = $info[0]; $info = $info[1]; } } if (is_array($info)) { if ($param->getPackageType() == 'extsrc' || $param->getPackageType() == 'extbin' || $param->getPackageType() == 'zendextsrc' || $param->getPackageType() == 'zendextbin') { $pkg =& $param->getPackageFile(); if ($instbin = $pkg->getInstalledBinary()) { $instpkg =& $instreg->getPackage($instbin, $pkg->getChannel()); } else { $instpkg =& $instreg->getPackage($pkg->getPackage(), $pkg->getChannel()); } foreach ($instpkg->getFilelist() as $name => $atts) { $pinfo = pathinfo($atts['installed_as']); if (!isset($pinfo['extension']) || in_array($pinfo['extension'], array('c', 'h'))) { continue; // make sure we don't match php_blah.h } if (strpos($pinfo['basename'], 'php_') === 0 && $pinfo['extension'] == 'dll' || $pinfo['extension'] == 'so' || $pinfo['extension'] == 'sl') { $binaries[] = array($atts['installed_as'], $pinfo); break; } } if (count($binaries)) { foreach ($binaries as $pinfo) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType()); PEAR::staticPopErrorHandling(); if (PEAR::isError($ret)) { $extrainfo[] = $ret->getMessage(); if ($param->getPackageType() == 'extsrc' || $param->getPackageType() == 'extbin') { $exttype = 'extension'; } else { ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_contents(); ob_end_clean(); $debug = function_exists('leak') ? '_debug' : ''; $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; $exttype = 'zend_extension' . $debug . $ts; } $extrainfo[] = 'You should add "' . $exttype . '=' . $pinfo[1]['basename'] . '" to php.ini'; } else { $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() . ' enabled in php.ini'; } } } } if ($this->config->get('verbose') > 0) { $channel = $param->getChannel(); $label = $reg->parsedPackageNameToString(array('channel' => $channel, 'package' => $param->getPackage(), 'version' => $param->getVersion())); $out = array('data' => "{$command} ok: {$label}"); if (isset($info['release_warnings'])) { $out['release_warnings'] = $info['release_warnings']; } $this->ui->outputData($out, $command); if (!isset($options['register-only']) && !isset($options['offline'])) { if ($this->config->isDefinedLayer('ftp')) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->ftpInstall($param); PEAR::staticPopErrorHandling(); if (PEAR::isError($info)) { $this->ui->outputData($info->getMessage()); $this->ui->outputData("remote install failed: {$label}"); } else { $this->ui->outputData("remote install ok: {$label}"); } } } } $deps = $param->getDeps(); if ($deps) { if (isset($deps['group'])) { $groups = $deps['group']; if (!isset($groups[0])) { $groups = array($groups); } foreach ($groups as $group) { if ($group['attribs']['name'] == 'default') { // default group is always installed, unless the user // explicitly chooses to install another group continue; } $extrainfo[] = $param->getPackage() . ': Optional feature ' . $group['attribs']['name'] . ' available (' . $group['attribs']['hint'] . ')'; } $extrainfo[] = $param->getPackage() . ': To install optional features use "pear install ' . $reg->parsedPackageNameToString(array('package' => $param->getPackage(), 'channel' => $param->getChannel()), true) . '#featurename"'; } } $pkg =& $instreg->getPackage($param->getPackage(), $param->getChannel()); // $pkg may be NULL if install is a 'fake' install via --packagingroot if (is_object($pkg)) { $pkg->setConfig($this->config); if ($list = $pkg->listPostinstallScripts()) { $pn = $reg->parsedPackageNameToString(array('channel' => $param->getChannel(), 'package' => $param->getPackage()), true); $extrainfo[] = $pn . ' has post-install scripts:'; foreach ($list as $file) { $extrainfo[] = $file; } $extrainfo[] = $param->getPackage() . ': Use "pear run-scripts ' . $pn . '" to finish setup.'; $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; } } } else { return $this->raiseError("{$command} failed"); } } if (count($extrainfo)) { foreach ($extrainfo as $info) { $this->ui->outputData($info); } } return true; }
/** * Verify that uninstalling packages passed in to command line is OK. * * @param PEAR_Installer $dl * @return PEAR_Error|true */ function validatePackageUninstall(&$dl) { if (PEAR::isError($this->_dependencydb)) { return $this->_dependencydb; } $params = array(); // construct an array of "downloaded" packages to fool the package dependency checker // into using these to validate uninstalls of circular dependencies $downloaded =& $dl->getUninstallPackages(); foreach ($downloaded as $i => $pf) { if (!class_exists('PEAR_Downloader_Package')) { require_once 'PEAR/Downloader/Package.php'; } $dp =& new PEAR_Downloader_Package($dl); $dp->setPackageFile($downloaded[$i]); $params[$i] =& $dp; } // check cache $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' . strtolower($this->_currentPackage['package']); if (isset($dl->___uninstall_package_cache)) { $badpackages = $dl->___uninstall_package_cache; if (isset($badpackages[$memyselfandI]['warnings'])) { foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { $dl->log(0, $warning[0]); } } if (isset($badpackages[$memyselfandI]['errors'])) { foreach ($badpackages[$memyselfandI]['errors'] as $error) { if (is_array($error)) { $dl->log(0, $error[0]); } else { $dl->log(0, $error->getMessage()); } } if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { return $this->warning('warning: %s should not be uninstalled, other installed packages depend ' . 'on this package'); } return $this->raiseError('%s cannot be uninstalled, other installed packages depend on this package'); } return true; } // first, list the immediate parents of each package to be uninstalled $perpackagelist = array(); $allparents = array(); foreach ($params as $i => $param) { $a = array('channel' => strtolower($param->getChannel()), 'package' => strtolower($param->getPackage())); $deps = $this->_dependencydb->getDependentPackages($a); if ($deps) { foreach ($deps as $d) { $pardeps = $this->_dependencydb->getDependencies($d); foreach ($pardeps as $dep) { if (strtolower($dep['dep']['channel']) == $a['channel'] && strtolower($dep['dep']['name']) == $a['package']) { if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) { $perpackagelist[$a['channel'] . '/' . $a['package']] = array(); } $perpackagelist[$a['channel'] . '/' . $a['package']][] = array($d['channel'] . '/' . $d['package'], $dep); if (!isset($allparents[$d['channel'] . '/' . $d['package']])) { $allparents[$d['channel'] . '/' . $d['package']] = array(); } if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) { $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array(); } $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']][] = array($d, $dep); } } } } } // next, remove any packages from the parents list that are not installed $remove = array(); foreach ($allparents as $parent => $d1) { foreach ($d1 as $d) { if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) { continue; } $remove[$parent] = true; } } // next remove any packages from the parents list that are not passed in for // uninstallation foreach ($allparents as $parent => $d1) { foreach ($d1 as $d) { foreach ($params as $param) { if (strtolower($param->getChannel()) == $d[0][0]['channel'] && strtolower($param->getPackage()) == $d[0][0]['package']) { // found it continue 3; } } $remove[$parent] = true; } } // remove all packages whose dependencies fail // save which ones failed for error reporting $badchildren = array(); do { $fail = false; foreach ($remove as $package => $unused) { if (!isset($allparents[$package])) { continue; } foreach ($allparents[$package] as $kid => $d1) { foreach ($d1 as $depinfo) { if ($depinfo[1]['type'] != 'optional') { if (isset($badchildren[$kid])) { continue; } $badchildren[$kid] = true; $remove[$kid] = true; $fail = true; continue 2; } } } if ($fail) { // start over, we removed some children continue 2; } } } while ($fail); // next, construct the list of packages that can't be uninstalled $badpackages = array(); $save = $this->_currentPackage; foreach ($perpackagelist as $package => $packagedeps) { foreach ($packagedeps as $parent) { if (!isset($remove[$parent[0]])) { continue; } $packagename = $this->_registry->parsePackageName($parent[0]); $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']); $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']); $packagename['package'] = $pa->getPackage(); $this->_currentPackage = $packagename; // parent is not present in uninstall list, make sure we can actually // uninstall it (parent dep is optional) $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']); $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']); $parentname['package'] = $pa->getPackage(); $parent[1]['dep']['package'] = $parentname['package']; $parent[1]['dep']['channel'] = $parentname['channel']; if ($parent[1]['type'] == 'optional') { $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl); if ($test !== true) { $badpackages[$package]['warnings'][] = $test; } } else { $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl); if ($test !== true) { $badpackages[$package]['errors'][] = $test; } } } } $this->_currentPackage = $save; $dl->___uninstall_package_cache = $badpackages; if (isset($badpackages[$memyselfandI])) { if (isset($badpackages[$memyselfandI]['warnings'])) { foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { $dl->log(0, $warning[0]); } } if (isset($badpackages[$memyselfandI]['errors'])) { foreach ($badpackages[$memyselfandI]['errors'] as $error) { if (is_array($error)) { $dl->log(0, $error[0]); } else { $dl->log(0, $error->getMessage()); } } if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { return $this->warning('warning: %s should not be uninstalled, other installed packages depend ' . 'on this package'); } return $this->raiseError('%s cannot be uninstalled, other installed packages depend on this package'); } } return true; }
/** * (non-PHPdoc) * @see lib/Faett/Core/Interfaces/Faett_Core_Interfaces_Service#packageExists($packageName, $alias) */ public function packageExists($packageName, $alias) { return $this->_registry->packageExists($packageName, $alias); }
function _validatePackageDownload($dep, $required, $params, $depv1 = false) { $dep['package'] = $dep['name']; if (isset($dep['uri'])) { $dep['channel'] = '__uri'; } $depname = $this->_registry->parsedPackageNameToString($dep, true); $found = false; foreach ($params as $param) { if ($param->isEqual(array('package' => $dep['name'], 'channel' => $dep['channel']))) { $found = true; break; } if ($depv1 && $dep['channel'] == 'pear.php.net') { if ($param->isEqual(array('package' => $dep['name'], 'channel' => 'pecl.php.net'))) { $found = true; break; } } } if (!$found && isset($dep['providesextension'])) { foreach ($params as $param) { if ($param->isExtension($dep['providesextension'])) { $found = true; break; } } } if ($found) { $version = $param->getVersion(); $installed = false; $downloaded = true; } else { if ($this->_registry->packageExists($dep['name'], $dep['channel'])) { $installed = true; $downloaded = false; $version = $this->_registry->packageinfo($dep['name'], 'version', $dep['channel']); } else { if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'], 'pear.php.net')) { $installed = true; $downloaded = false; $version = $this->_registry->packageinfo($dep['name'], 'version', 'pear.php.net'); } else { $version = 'not installed or downloaded'; $installed = false; $downloaded = false; } } } $extra = $this->_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } } if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended']) && !isset($dep['exclude'])) { if ($installed || $downloaded) { $installed = $installed ? 'installed' : 'downloaded'; if (isset($dep['conflicts'])) { if ($version) { $rest = ", {$installed} version is " . $version; } else { $rest = ''; } if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest); } else { return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest); } } return true; } else { if (isset($dep['conflicts'])) { return true; } if ($required) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires package "' . $depname . '"' . $extra); } else { return $this->warning('warning: %s requires package "' . $depname . '"' . $extra); } } else { return $this->warning('%s can optionally use package "' . $depname . '"' . $extra); } } } if (!$installed && !$downloaded) { if (isset($dep['conflicts'])) { return true; } if ($required) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires package "' . $depname . '"' . $extra); } else { return $this->warning('warning: %s requires package "' . $depname . '"' . $extra); } } else { return $this->warning('%s can optionally use package "' . $depname . '"' . $extra); } } $fail = false; if (isset($dep['min'])) { if (version_compare($version, $dep['min'], '<')) { $fail = true; } } if (isset($dep['max'])) { if (version_compare($version, $dep['max'], '>')) { $fail = true; } } if ($fail && !isset($dep['conflicts'])) { $installed = $installed ? 'installed' : 'downloaded'; $dep['package'] = $dep['name']; $dep = $this->_registry->parsedPackageNameToString($dep, true); if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s requires package "' . $depname . '"' . $extra . ", {$installed} version is " . $version); } else { return $this->warning('warning: %s requires package "' . $depname . '"' . $extra . ", {$installed} version is " . $version); } } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts']) && !isset($dep['exclude'])) { $installed = $installed ? 'installed' : 'downloaded'; if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . ", {$installed} version is " . $version); } else { return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . ", {$installed} version is " . $version); } } if (isset($dep['exclude'])) { $installed = $installed ? 'installed' : 'downloaded'; foreach ($dep['exclude'] as $exclude) { if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s is not compatible with ' . $installed . ' package "' . $depname . '" version ' . $exclude); } else { return $this->warning('warning: %s is not compatible with ' . $installed . ' package "' . $depname . '" version ' . $exclude); } } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) { $installed = $installed ? 'installed' : 'downloaded'; if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . ", {$installed} version is " . $version); } else { return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . ", {$installed} version is " . $version); } } } } if (isset($dep['recommended'])) { $installed = $installed ? 'installed' : 'downloaded'; if (version_compare($version, $dep['recommended'], '==')) { return true; } else { if (!$found && $installed) { $param = $this->_registry->getPackage($dep['name'], $dep['channel']); } if ($param) { $found = false; foreach ($params as $parent) { if ($parent->isEqual($this->_currentPackage)) { $found = true; break; } } if ($found) { if ($param->isCompatible($parent)) { return true; } } else { // this is for validPackage() calls $parent = $this->_registry->getPackage($this->_currentPackage['package'], $this->_currentPackage['channel']); if ($parent !== null) { if ($param->isCompatible($parent)) { return true; } } } } if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) && !isset($this->_options['loose'])) { return $this->raiseError('%s dependency package "' . $depname . '" ' . $installed . ' version ' . $version . ' is not the recommended version ' . $dep['recommended'] . ', but may be compatible, use --force to install'); } else { return $this->warning('warning: %s dependency package "' . $depname . '" ' . $installed . ' version ' . $version . ' is not the recommended version ' . $dep['recommended']); } } } return true; }
/** * @return false|PEAR_Error|string false if loop should be broken out of, * string if the file was downloaded, * PEAR_Error on exception * @access private */ function _downloadNonFile($pkgfile) { $origpkgfile = $pkgfile; $state = null; $pkgfile = $this->extractDownloadFileName($pkgfile, $version); if (preg_match('#^(http|ftp)://#', $pkgfile)) { return $this->_downloadFile($pkgfile, $version, $origpkgfile); } if (!$this->validPackageName($pkgfile)) { return $this->raiseError("Package name '{$pkgfile}' not valid"); } // ignore packages that are installed unless we are upgrading $curinfo = $this->_registry->packageInfo($pkgfile); if ($this->_registry->packageExists($pkgfile) && empty($this->_options['upgrade']) && empty($this->_options['force'])) { $this->log(0, "Package '{$curinfo['package']}' already installed, skipping"); return false; } if (in_array($pkgfile, $this->_toDownload)) { return false; } $releases = $this->_remote->call('package.info', $pkgfile, 'releases', true); if (!count($releases)) { return $this->raiseError("No releases found for package '{$pkgfile}'"); } // Want a specific version/state if ($version !== null) { // Passed Foo-1.2 if ($this->validPackageVersion($version)) { if (!isset($releases[$version])) { return $this->raiseError("No release with version '{$version}' found for '{$pkgfile}'"); } // Passed Foo-alpha } elseif (in_array($version, $this->getReleaseStates())) { $state = $version; $version = 0; foreach ($releases as $ver => $inf) { if ($inf['state'] == $state && version_compare("{$version}", "{$ver}") < 0) { $version = $ver; break; } } if ($version == 0) { return $this->raiseError("No release with state '{$state}' found for '{$pkgfile}'"); } // invalid postfix passed } else { return $this->raiseError("Invalid postfix '-{$version}', be sure to pass a valid PEAR " . "version number or release state"); } // Guess what to download } else { $states = $this->betterStates($this->_preferredState, true); $possible = false; $version = 0; foreach ($releases as $ver => $inf) { if (in_array($inf['state'], $states) && version_compare("{$version}", "{$ver}") < 0) { $version = $ver; break; } } if ($version === 0 && !isset($this->_options['force'])) { return $this->raiseError('No release with state equal to: \'' . implode(', ', $states) . "' found for '{$pkgfile}'"); } elseif ($version === 0) { $this->log(0, "Warning: {$pkgfile} is state '{$inf['state']}' which is less stable " . "than state '{$this->_preferredState}'"); } } // Check if we haven't already the version if (empty($this->_options['force']) && !is_null($curinfo)) { if ($curinfo['version'] == $version) { $this->log(0, "Package '{$curinfo['package']}-{$curinfo['version']}' already installed, skipping"); return false; } elseif (version_compare("{$version}", "{$curinfo['version']}") < 0) { $this->log(0, "Package '{$curinfo['package']}' version '{$curinfo['version']}' " . " is installed and {$curinfo['version']} is > requested '{$version}', skipping"); return false; } } $this->_toDownload[] = $pkgfile; return $this->_downloadFile($pkgfile, $version, $origpkgfile, $state); }
/** * 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(); } else { $descfile = $pkgfile; $pkg = $this->_parsePackageXml($descfile); if (PEAR::isError($pkg)) { return $pkg; } } $tmpdir = dirname($descfile); if (realpath($descfile) != realpath($pkgfile)) { // Use the temp_dir since $descfile can contain the download dir path $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net'); $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"'); $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'])) { $regdir = $this->_prependPath($this->config->get('php_dir', null, 'pear.php.net'), $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($regdir); if (!$installregistry->channelExists($channel, true)) { // we need to fake a channel-discover of this channel $chanobj = $this->_registry->getChannel($channel, true); $installregistry->addChannel($chanobj); } $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']) && (file_exists($this->config->get('php_dir')) && 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; } // ensure we have the most accurate registry $installregistry->flushFileMap(); $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())) { if (isset($parentreg['filelist'][$file])) { unset($parentreg['filelist'][$file]); } else { $pos = strpos($file, '/'); $basedir = substr($file, 0, $pos); $file2 = substr($file, $pos + 1); if (isset($parentreg['filelist'][$file2]['baseinstalldir']) && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir) { unset($parentreg['filelist'][$file2]); } } unset($test[$file]); } } else { if (strtolower($param->getChannel()) != 'pear.php.net') { continue; } if (strtolower($info) == strtolower($param->getPackage())) { if (isset($parentreg['filelist'][$file])) { unset($parentreg['filelist'][$file]); } else { $pos = strpos($file, '/'); $basedir = substr($file, 0, $pos); $file2 = substr($file, $pos + 1); if (isset($parentreg['filelist'][$file2]['baseinstalldir']) && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir) { unset($parentreg['filelist'][$file2]); } } unset($test[$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 (count($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); } if (!isset($options['soft'])) { $this->log(0, "WARNING: {$msg}"); } } } } // }}} $this->startFileTransaction(); $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['upgrade']) && empty($options['soft'])) { // checks to do only when installing new packages if (empty($options['force']) && $test) { return $this->raiseError("{$channel}/{$pkgname} is already installed"); } } else { // Upgrade 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})"); } } } // Do cleanups for upgrade and install, remove old release's files first if ($test && 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); } 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"); } } if (substr($pkgfile, -4) != '.xml') { $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); } $this->configSet('default_channel', $channel); // {{{ install files $ver = $pkg->getPackagexmlVersion(); if (version_compare($ver, '2.0', '>=')) { $filelist = $pkg->getInstallationFilelist(); } else { $filelist = $pkg->getFileList(); } if (PEAR::isError($filelist)) { return $filelist; } $p =& $installregistry->getPackage($pkgname, $channel); $dirtree = empty($options['register-only']) && $p ? $p->getDirTree() : false; $pkg->resetFilelist(); $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), 'version', $pkg->getChannel())); foreach ($filelist as $file => $atts) { $this->expectError(PEAR_INSTALLER_FAILED); if ($pkg->getPackagexmlVersion() == '1.0') { $res = $this->_installFile($file, $atts, $tmpdir, $options); } else { $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $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); } if (!isset($options['soft'])) { $this->log(0, "Warning: " . $res->getMessage()); } } $real = isset($atts['attribs']) ? $atts['attribs'] : $atts; if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') { // 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 { if ($dirtree) { $this->startFileTransaction(); // attempt to delete empty directories uksort($dirtree, array($this, '_sortDirs')); foreach ($dirtree as $dir => $notused) { $this->addFileOperation('rmdir', array($dir)); } $this->commitFileTransaction(); } $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); }
$config =& PEAR_Config::singleton($prefix . "/pear.conf", ''); } else { $config =& PEAR_Config::singleton(); } $config->set('preferred_state', 'stable'); foreach ($config_vars as $var) { $config->set($var, ${$var}); } $config->store(); $registry = new PEAR_Registry($php_dir); PEAR_Command::setFrontendType('CLI'); $install =& PEAR_Command::factory('install', $config); $install_options = array('nodeps' => true, 'force' => true); foreach ($tarball as $pkg => $src) { $options = $install_options; if ($registry->packageExists($pkg)) { $options['upgrade'] = true; } $install->run('install', $options, array($src)); displayHTMLProgress($progress += round(29 / count($tarball))); } displayHTMLProgress($progress = 99); // Base installation finished ini_restore("include_path"); if (!WEBINSTALLER) { $sep = WINDOWS ? ';' : ':'; $include_path = explode($sep, ini_get('include_path')); if (WINDOWS) { $found = false; $t = strtolower($php_dir); foreach ($include_path as $path) {
function doShellTest($command, $options, $params) { $this->pushErrorHandling(PEAR_ERROR_RETURN); $reg = new PEAR_Registry($this->config->get('php_dir')); // "pear shell-test Foo" if (sizeof($params) == 1) { if (!$reg->packageExists($params[0])) { exit(1); } // "pear shell-test Foo 1.0" } elseif (sizeof($params) == 2) { $v = $reg->packageInfo($params[0], 'version'); if (!$v || !version_compare("{$v}", "{$params[1]}", "ge")) { exit(1); } // "pear shell-test Foo ge 1.0" } elseif (sizeof($params) == 3) { $v = $reg->packageInfo($params[0], 'version'); if (!$v || !version_compare("{$v}", "{$params[2]}", $params[1])) { exit(1); } } else { $this->popErrorHandling(); $this->raiseError("{$command}: expects 1 to 3 parameters"); exit(1); } }
/** * Check if a package is installed */ function packageInstalled($package_name, $version = null, $pear_user_config = null) { if (is_null($pear_user_config)) { $config = new PEAR_Config(); } else { $config = new PEAR_Config($pear_user_config); } $reg = new PEAR_Registry($config->get('php_dir')); if (is_null($version)) { return $reg->packageExists($package_name); } else { $installed = $reg->packageInfo($package_name); return version_compare($version, $installed['version'], '<='); } }