setPackageFile() public method

Set the package.xml object for this downloaded package
public setPackageFile ( PEAR_PackageFile_v1 | PEAR_PackageFile_v2 &$pkg )
$pkg PEAR_PackageFile_v1 | PEAR_PackageFile_v2
Esempio n. 1
0
 /**
  * validate a downloaded package against installed packages
  * 
  * As of PEAR 1.4.3, this will only validate
  *
  * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
  *              $pkg package identifier (either
  *                   array('package' => blah, 'channel' => blah) or an array with
  *                   index 'info' referencing an object)
  * @param PEAR_Downloader $dl
  * @param array $params full list of packages to install
  * @return true|PEAR_Error
  */
 function validatePackage($pkg, &$dl, $params = array())
 {
     if (is_array($pkg) && isset($pkg['info'])) {
         $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
     } else {
         $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
     }
     $fail = false;
     if ($deps) {
         if (!class_exists('PEAR_Downloader_Package')) {
             require_once 'PEAR/Downloader/Package.php';
         }
         $dp = new PEAR_Downloader_Package($dl);
         if (is_object($pkg)) {
             $dp->setPackageFile($pkg);
         } else {
             $dp->setDownloadURL($pkg);
         }
         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
         foreach ($deps as $channel => $info) {
             foreach ($info as $package => $ds) {
                 foreach ($params as $packd) {
                     if (strtolower($packd->getPackage()) == strtolower($package) && $packd->getChannel() == $channel) {
                         $dl->log(3, 'skipping installed package check of "' . $this->_registry->parsedPackageNameToString(array('channel' => $channel, 'package' => $package), true) . '", version "' . $packd->getVersion() . '" will be ' . 'downloaded and installed');
                         continue 2;
                         // jump to next package
                     }
                 }
                 foreach ($ds as $d) {
                     $checker = new PEAR_Dependency2($this->_config, $this->_options, array('channel' => $channel, 'package' => $package), $this->_state);
                     $dep = $d['dep'];
                     $required = $d['type'] == 'required';
                     $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
                     if (is_array($ret)) {
                         $dl->log(0, $ret[0]);
                     } elseif (PEAR::isError($ret)) {
                         $dl->log(0, $ret->getMessage());
                         $fail = true;
                     }
                 }
             }
         }
         PEAR::popErrorHandling();
     }
     if ($fail) {
         return $this->raiseError('%s cannot be installed, conflicts with installed packages');
     }
     return true;
 }
 function doMakeRPM($command, $options, $params)
 {
     require_once 'System.php';
     require_once 'Archive/Tar.php';
     if (sizeof($params) != 1) {
         return $this->raiseError("bad parameter(s), try \"help {$command}\"");
     }
     if (!file_exists($params[0])) {
         return $this->raiseError("file does not exist: {$params['0']}");
     }
     $reg =& $this->config->getRegistry();
     $pkg =& $this->getPackageFile($this->config, $this->_debug);
     $pf =& $pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
     if (PEAR::isError($pf)) {
         $u = $pf->getUserinfo();
         if (is_array($u)) {
             foreach ($u as $err) {
                 if (is_array($err)) {
                     $err = $err['message'];
                 }
                 $this->ui->outputData($err);
             }
         }
         return $this->raiseError("{$params['0']} is not a valid package");
     }
     $tmpdir = System::mktemp(array('-d', 'pear2rpm'));
     $instroot = System::mktemp(array('-d', 'pear2rpm'));
     $tmp = $this->config->get('verbose');
     $this->config->set('verbose', 0);
     $installer = $this->getInstaller($this->ui);
     require_once 'PEAR/Downloader/Package.php';
     $pack = new PEAR_Downloader_Package($installer);
     $pack->setPackageFile($pf);
     $params[0] =& $pack;
     $installer->setOptions(array('installroot' => $instroot, 'nodeps' => true, 'soft' => true));
     $installer->setDownloadedPackages($params);
     $info = $installer->install($params[0], array('installroot' => $instroot, 'nodeps' => true, 'soft' => true));
     $pkgdir = $pf->getPackage() . '-' . $pf->getVersion();
     $info['rpm_xml_dir'] = '/var/lib/pear';
     $this->config->set('verbose', $tmp);
     if (isset($options['spec-template'])) {
         $spec_template = $options['spec-template'];
     } else {
         $spec_template = '@DATA-DIR@/PEAR/template.spec';
     }
     $info['possible_channel'] = '';
     $info['extra_config'] = '';
     if (isset($options['rpm-pkgname'])) {
         $rpm_pkgname_format = $options['rpm-pkgname'];
     } else {
         if ($pf->getChannel() == 'pear.php.net' || $pf->getChannel() == 'pecl.php.net') {
             $alias = 'PEAR';
         } else {
             $chan =& $reg->getChannel($pf->getChannel());
             $alias = $chan->getAlias();
             $alias = strtoupper($alias);
             $info['possible_channel'] = $pf->getChannel() . '/';
         }
         $rpm_pkgname_format = $alias . '::%s';
     }
     $info['extra_headers'] = '';
     $info['doc_files'] = '';
     $info['files'] = '';
     $info['package2xml'] = '';
     $info['rpm_package'] = sprintf($rpm_pkgname_format, $pf->getPackage());
     $srcfiles = 0;
     foreach ($info['filelist'] as $name => $attr) {
         if (!isset($attr['role'])) {
             continue;
         }
         $name = preg_replace('![/:\\\\]!', '/', $name);
         if ($attr['role'] == 'doc') {
             $info['doc_files'] .= " {$name}";
             // Map role to the rpm vars
         } else {
             $c_prefix = '%{_libdir}/php/pear';
             switch ($attr['role']) {
                 case 'php':
                     $prefix = $c_prefix;
                     break;
                 case 'ext':
                     $prefix = '%{_libdir}/php';
                     break;
                     // XXX good place?
                 // XXX good place?
                 case 'src':
                     $srcfiles++;
                     $prefix = '%{_includedir}/php';
                     break;
                     // XXX good place?
                 // XXX good place?
                 case 'test':
                     $prefix = "{$c_prefix}/tests/" . $pf->getPackage();
                     break;
                 case 'data':
                     $prefix = "{$c_prefix}/data/" . $pf->getPackage();
                     break;
                 case 'script':
                     $prefix = '%{_bindir}';
                     break;
                 default:
                     // non-standard roles
                     $prefix = "{$c_prefix}/{$attr['role']}/" . $pf->getPackage();
                     $info['extra_config'] .= "\n        -d {$attr[role]}_dir={$c_prefix}/{$attr[role]} \\";
                     $this->ui->outputData('WARNING: role "' . $attr['role'] . '" used, ' . 'and will be installed in "' . $c_prefix . '/' . $attr['role'] . '/' . $pf->getPackage() . ' - hand-edit the final .spec if this is wrong', $command);
                     break;
             }
             $name = str_replace('\\', '/', $name);
             $info['files'] .= "{$prefix}/{$name}\n";
         }
     }
     if ($srcfiles > 0) {
         require_once 'OS/Guess.php';
         $os = new OS_Guess();
         $arch = $os->getCpu();
     } else {
         $arch = 'noarch';
     }
     $cfg = array('master_server', 'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'test_dir');
     foreach ($cfg as $k) {
         if ($k == 'master_server') {
             $chan = $reg->getChannel($pf->getChannel());
             $info[$k] = $chan->getServer();
             continue;
         }
         $info[$k] = $this->config->get($k);
     }
     $info['arch'] = $arch;
     $fp = @fopen($spec_template, "r");
     if (!$fp) {
         return $this->raiseError("could not open RPM spec file template {$spec_template}: {$php_errormsg}");
     }
     $info['package'] = $pf->getPackage();
     $info['version'] = $pf->getVersion();
     $info['release_license'] = $pf->getLicense();
     if ($pf->getDeps()) {
         if ($pf->getPackagexmlVersion() == '1.0') {
             $requires = $conflicts = array();
             foreach ($pf->getDeps() as $dep) {
                 if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                     continue;
                 }
                 if ($dep['type'] != 'pkg') {
                     continue;
                 }
                 if (isset($dep['channel']) && $dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') {
                     $chan =& $reg->getChannel($dep['channel']);
                     $package = strtoupper($chan->getAlias()) . '::' . $dep['name'];
                 } else {
                     $package = 'PEAR::' . $dep['name'];
                 }
                 $trans = array('>' => '>', '<' => '<', '>=' => '>=', '<=' => '<=', '=' => '=', 'gt' => '>', 'lt' => '<', 'ge' => '>=', 'le' => '<=', 'eq' => '=');
                 if ($dep['rel'] == 'has') {
                     $requires[] = $package;
                 } elseif ($dep['rel'] == 'not') {
                     $conflicts[] = $package;
                 } elseif ($dep['rel'] == 'ne') {
                     $conflicts[] = $package . ' = ' . $dep['version'];
                 } elseif (isset($trans[$dep['rel']])) {
                     $requires[] = $package . ' ' . $trans[$dep['rel']] . ' ' . $dep['version'];
                 }
             }
             if (count($requires)) {
                 $info['extra_headers'] .= 'Requires: ' . implode(', ', $requires) . "\n";
             }
             if (count($conflicts)) {
                 $info['extra_headers'] .= 'Conflicts: ' . implode(', ', $conflicts) . "\n";
             }
         } else {
             $info['package2xml'] = '2';
             // tell the spec to use package2.xml
             $requires = $conflicts = array();
             $deps = $pf->getDeps(true);
             if (isset($deps['required']['package'])) {
                 if (!isset($deps['required']['package'][0])) {
                     $deps['required']['package'] = array($deps['required']['package']);
                 }
                 foreach ($deps['required']['package'] as $dep) {
                     if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') {
                         $chan =& $reg->getChannel($dep['channel']);
                         $package = strtoupper($chan->getAlias()) . '::' . $dep['name'];
                     } else {
                         $package = 'PEAR::' . $dep['name'];
                     }
                     if (isset($dep['conflicts']) && (isset($dep['min']) || isset($dep['max']))) {
                         $deprange = array();
                         if (isset($dep['min'])) {
                             $deprange[] = array($dep['min'], '>=');
                         }
                         if (isset($dep['max'])) {
                             $deprange[] = array($dep['max'], '<=');
                         }
                         if (isset($dep['exclude'])) {
                             if (!is_array($dep['exclude']) || !isset($dep['exclude'][0])) {
                                 $dep['exclude'] = array($dep['exclude']);
                             }
                             if (count($deprange)) {
                                 $excl = $dep['exclude'];
                                 // change >= to > if excluding the min version
                                 // change <= to < if excluding the max version
                                 for ($i = 0; $i < count($excl); $i++) {
                                     if (isset($deprange[0]) && $excl[$i] == $deprange[0][0]) {
                                         $deprange[0][1] = '<';
                                         unset($dep['exclude'][$i]);
                                     }
                                     if (isset($deprange[1]) && $excl[$i] == $deprange[1][0]) {
                                         $deprange[1][1] = '>';
                                         unset($dep['exclude'][$i]);
                                     }
                                 }
                             }
                             if (count($dep['exclude'])) {
                                 $dep['exclude'] = array_values($dep['exclude']);
                                 $newdeprange = array();
                                 // remove excludes that are outside the existing range
                                 for ($i = 0; $i < count($dep['exclude']); $i++) {
                                     if ($dep['exclude'][$i] < $dep['min'] || $dep['exclude'][$i] > $dep['max']) {
                                         unset($dep['exclude'][$i]);
                                     }
                                 }
                                 $dep['exclude'] = array_values($dep['exclude']);
                                 usort($dep['exclude'], 'version_compare');
                                 // take the remaining excludes and
                                 // split the dependency into sub-ranges
                                 $lastmin = $deprange[0];
                                 for ($i = 0; $i < count($dep['exclude']) - 1; $i++) {
                                     $newdeprange[] = '(' . $package . " {$lastmin[1]} {$lastmin[0]} and " . $package . ' < ' . $dep['exclude'][$i] . ')';
                                     $lastmin = array($dep['exclude'][$i], '>');
                                 }
                                 if (isset($dep['max'])) {
                                     $newdeprange[] = '(' . $package . " {$lastmin[1]} {$lastmin[0]} and " . $package . ' < ' . $dep['max'] . ')';
                                 }
                                 $conflicts[] = implode(' or ', $deprange);
                             } else {
                                 $conflicts[] = $package . " {$deprange[0][1]} {$deprange[0][0]}" . (isset($deprange[1]) ? " and {$package} {$deprange[1][1]} {$deprange[1][0]}" : '');
                             }
                         }
                         continue;
                     }
                     if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['exclude'])) {
                         if (isset($dep['conflicts'])) {
                             $conflicts[] = $package;
                         } else {
                             $requires[] = $package;
                         }
                     } else {
                         if (isset($dep['min'])) {
                             $requires[] = $package . ' >= ' . $dep['min'];
                         }
                         if (isset($dep['max'])) {
                             $requires[] = $package . ' <= ' . $dep['max'];
                         }
                         if (isset($dep['exclude'])) {
                             $ex = $dep['exclude'];
                             if (!is_array($ex)) {
                                 $ex = array($ex);
                             }
                             foreach ($ex as $ver) {
                                 $conflicts[] = $package . ' = ' . $ver;
                             }
                         }
                     }
                 }
                 require_once 'Archive/Tar.php';
                 $tar = new Archive_Tar($pf->getArchiveFile());
                 $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                 $a = $tar->extractInString('package2.xml');
                 $tar->popErrorHandling();
                 if ($a === null || PEAR::isError($a)) {
                     $info['package2xml'] = '';
                     // this doesn't have a package.xml version 1.0
                     $requires[] = 'PEAR::PEAR >= ' . $deps['required']['pearinstaller']['min'];
                 }
                 if (count($requires)) {
                     $info['extra_headers'] .= 'Requires: ' . implode(', ', $requires) . "\n";
                 }
                 if (count($conflicts)) {
                     $info['extra_headers'] .= 'Conflicts: ' . implode(', ', $conflicts) . "\n";
                 }
             }
         }
     }
     // remove the trailing newline
     $info['extra_headers'] = trim($info['extra_headers']);
     if (function_exists('file_get_contents')) {
         fclose($fp);
         $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\\1"]', file_get_contents($spec_template));
     } else {
         $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\\1"]', fread($fp, filesize($spec_template)));
         fclose($fp);
     }
     $spec_file = "{$info['rpm_package']}-{$info['version']}.spec";
     $wp = fopen($spec_file, "wb");
     if (!$wp) {
         return $this->raiseError("could not write RPM spec file {$spec_file}: {$php_errormsg}");
     }
     fwrite($wp, $spec_contents);
     fclose($wp);
     $this->ui->outputData("Wrote RPM spec file {$spec_file}", $command);
     return true;
 }
Esempio n. 3
0
 /**
  * Set the output macros based on a package source
  */
 function _doMakeRPMFromPackage($source_file, $command, $options, $params)
 {
     // Merge the "core" output macros with those for packages only
     $this->_output += $this->_output_package;
     // Set the name of the template spec file to use by default
     $this->_template_spec_name = 'template.spec';
     // Create a PEAR_PackageFile object and fill it with info from the
     // source package
     $reg =& $this->config->getRegistry();
     $pkg =& $this->getPackageFile($this->config, $this->_debug);
     $pf =& $pkg->fromAnyFile($source_file, PEAR_VALIDATE_NORMAL);
     if (PEAR::isError($pf)) {
         $u = $pf->getUserinfo();
         if (is_array($u)) {
             foreach ($u as $err) {
                 if (is_array($err)) {
                     $err = $err['message'];
                 }
                 $this->ui->outputData($err);
             }
         }
         return $this->raiseError("{$source_file} is not a valid package");
     }
     // Install the package into a temporary directory
     $tmpdir = $this->makeTempDir();
     $instroot = $this->makeTempDir();
     // Save a channel object for the channel our package is part of
     // We will need this later to stick back into the temporary
     // installation directory
     $chan = $reg->getChannel($pf->getChannel(), true);
     if (PEAR::isError($chan)) {
         $this->ui->outputData($chan->getMessage());
         return $this->raiseError("Could not find channel data for channel '" . $pf->getChannel() . " - you need to channel-discover or channel-add " . "the channel before building packages based on it.");
     }
     // Set the role prefixes - package won't actually be installed here
     // but we can pull the final install paths back out later to put into
     // our spec
     foreach ($this->_file_prefixes as $role => $prefix) {
         // if role is 'script' the corresponding option is bin_dir
         if ($role == 'script') {
             $role = 'bin';
         }
         // save the original config options to restore later
         $orig_config_options["{$role}_dir"] = $this->config->get("{$role}_dir");
         // Substitute the package name into the file prefix
         $prefix = str_replace('%s', $pf->getPackage(), $prefix);
         // Set the temporary role prefix for installation
         $this->config->set("{$role}_dir", $prefix);
     }
     // Construct a fake registry inside the ultimate destination
     // temporary directory, and load the necessary channel into it
     $regdir = $instroot . $this->config->get('php_dir');
     $fakereg = new PEAR_Registry($regdir);
     $fakereg->addChannel($chan);
     $tmp = $this->config->get('verbose');
     $this->config->set('verbose', 0);
     $installer = $this->getInstaller($this->ui);
     $installer->setConfig($this->config);
     require_once 'PEAR/Downloader/Package.php';
     $pack = new PEAR_Downloader_Package($installer);
     $pack->setPackageFile($pf);
     $params[0] =& $pack;
     $installer->setOptions(array('packagingroot' => $instroot, 'nodeps' => true, 'soft' => true));
     $installer->setDownloadedPackages($params);
     // Don't change $params[0] below to $source_file - it's not the same
     // any more (see $params[0] a few lines above here)
     $package_info = $installer->install($params[0], array('packagingroot' => $instroot, 'nodeps' => true, 'soft' => true));
     if (PEAR::isError($package_info)) {
         $this->ui->outputData($package_info->getMessage());
         return $this->raiseError('Failed to do a temporary installation of the package');
     }
     // Restore the original config options
     foreach ($orig_config_options as $key => $val) {
         $this->config->set($key, $val);
     }
     // Restore the original config verbosity
     $this->config->set('verbose', $tmp);
     // Set up some of the basic macros
     $this->_output['rpm_package'] = $this->_getRPMName($pf->getPackage(), $pf->getChannel(), null, 'pkg');
     $this->_output['description'] = wordwrap($package_info['description']);
     $this->_output['summary'] = trim($package_info['summary']);
     $this->_output['possible_channel'] = $pf->getChannel();
     $this->_output['channel_alias'] = $this->_getChannelAlias($pf->getPackage(), $pf->getChannel());
     $this->_output['package'] = $pf->getPackage();
     $this->_output['version'] = $pf->getVersion();
     $this->_output['release_license'] = $pf->getLicense();
     $this->_output['release_state'] = $pf->getState();
     // Remove trailing dots from summaries
     if (substr($this->_output['summary'], -1) == '.') {
         $this->_output['summary'] = substr($this->_output['summary'], 0, -1);
     }
     // Figure out the master server for the package's channel
     $chan = $reg->getChannel($pf->getChannel());
     $this->_output['master_server'] = $chan->getServer();
     // Put some standard PEAR config options into the output macros. These
     // will probably be deprecated in future
     $cfg = array('php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'test_dir');
     foreach ($cfg as $k) {
         $this->_output[$k] = $this->config->get($k);
     }
     // Generate the Requires and Conflicts for the RPM
     if ($pf->getDeps()) {
         $this->_generatePackageDeps($pf);
     }
     // Hook to support virtual Provides, where the dependency name differs
     // from the package name
     $rpmdep = $this->_getRPMName($pf->getPackage(), $pf->getChannel(), null, 'pkgdep');
     if (!empty($rpmdep) && $rpmdep != $this->_output['rpm_package']) {
         $this->_output['extra_headers'] .= $this->_formatRpmHeader('Provides', "{$rpmdep} = %{version}") . "\n";
     }
     // Create the list of files in the package
     foreach ($package_info['filelist'] as $filename => $attr) {
         // Ignore files with no role set or that didn't get installed
         if (!isset($attr['role']) || !isset($attr['installed_as'])) {
             continue;
         }
         $installed_filename = $attr['installed_as'];
         $role = $attr['role'];
         // Handle custom roles; set prefix
         // TODO: This is not tested and probably doesn't work, because:
         // a) package probably needs a custom file role package to build
         // b) [role]_dir wasn't set earlier before we did the test install
         if (!isset($this->_file_prefixes[$role])) {
             $this->_file_prefixes[$role] = $this->_file_prefixes['php'] . "/{$role}/%s";
             $this->_output['extra_config'] .= "\n        -d {$role}_dir=" . $this->_file_prefixes[$role] . "\\";
             $this->ui->outputData("WARNING: role '{$role}' used, " . 'and will be installed in "' . str_replace('%s', $pf->getPackage(), $this->_file_prefixes[$role]) . ' - hand-edit the final .spec if this is wrong', $command);
         }
         // Add to master file list
         $file_list[$role][] = $installed_filename;
     }
     // Build the master file lists
     foreach ($file_list as $role => $files) {
         // Docs are handled separately below; 'src' shouldn't be in RPM
         if ($role == 'doc' || $role == 'src') {
             continue;
         }
         // Master file list @files@ - recommended not to use
         $this->_output['files'] .= implode("\n", $files) . "\n";
         // Handle other roles specially: if the role puts files in a subdir
         // dedicated to the package in question (i.e. the prefix ends with
         // %s) we don't need to specify all the individual files
         if (in_array($role, array('php', 'test', 'data', 'script', 'cfg', 'www'))) {
             $macro_name = "{$role}_files_statement";
         } else {
             $macro_name = 'customrole_files_statement';
         }
         if (substr($this->_file_prefixes[$role], -2) == '%s') {
             $this->_output[$macro_name] = str_replace('%s', $pf->getPackage(), $this->_file_prefixes[$role]);
         } else {
             if ($role == 'cfg') {
                 $this->_output[$macro_name] = '%config(noreplace) ' . implode("\n%config(noreplace) ", $files);
             } else {
                 $this->_output[$macro_name] = implode("\n", $files);
             }
         }
     }
     $this->_output['files'] = trim($this->_output['files']);
     // Handle doc files
     if (isset($file_list['doc'])) {
         $this->_output['doc_files'] = 'docs/' . $pf->getPackage() . '/*';
         $this->_output['doc_files_statement'] = '%doc ' . $this->_output['doc_files'];
         $this->_output['doc_files_relocation_script'] = "mv %{buildroot}/docs .\n";
     }
     // Work out architecture
     // If there are 1 or more files with role="src", something needs compiling
     // and this is not a noarch package
     if (!isset($file_list['src'])) {
         $this->_output['arch_statement'] = $this->_formatRpmHeader('BuildArch', 'noarch') . "\n";
     }
     // If package is not from pear.php.net or pecl.php.net, we will need
     // to BuildRequire/Require a channel RPM
     if (!empty($this->_output['possible_channel']) && !in_array($this->_output['possible_channel'], $this->_standard_channels)) {
         $channel_dep = $this->_getRPMName($this->_output['package'], $this->_output['possible_channel'], null, 'chandep');
         $this->_output['extra_headers'] .= $this->_formatRpmHeader('BuildRequires', $channel_dep) . "\n";
         $this->_output['extra_headers'] .= $this->_formatRpmHeader('Requires', $channel_dep) . "\n";
     }
     // Remove any trailing newline from extra_headers
     $this->_output['extra_headers'] = trim($this->_output['extra_headers']);
 }