--- PEAR_Command_Packaging-0.2.0/usr/share/pear/PEAR/Command/Packaging.php 2011-04-10 18:34:41.270846822 +0300 +++ PEAR_Command_Packaging-0.2.0/usr/share/pear/PEAR/Command/Packaging.php 2011-05-03 09:26:29.397841813 +0300 @@ -54,6 +54,11 @@ 'arg' => 'FILE', 'doc' => 'Use FILE as RPM spec file template' ), + 'output' => array( + 'shortopt' => 'o', + 'arg' => 'FILE', + 'doc' => 'Use FILE as output filename' + ), 'rpm-release' => array( 'shortopt' => 'r', 'arg' => 'RELEASE', @@ -121,10 +126,10 @@ * $commands array above and in Packaging.xml so that it is consistent. */ var $_rpm_pkgname_format = array( - 'pkg' => '%C::%s', + 'pkg' => 'php-%c-%s', 'chan' => 'php-channel-%c', ); - + /** * The default format of various dependencies that might be generated in the * spec file. The currently-handled dependency types are: @@ -140,9 +145,11 @@ * %P = use the same as whatever rpm_pkgname_format is set to be */ var $_rpm_depname_format = array( - 'pkg' => '%P', + 'pkg' => 'php-%c-%s', 'ext' => 'php-%l', - 'php' => 'php', + 'pear-pkg' => 'php-pear-%s', + 'pecl-ext' => 'php-pecl-%l', + 'php' => 'php-common', 'chan' => 'php-channel(%n)', ); @@ -159,7 +166,7 @@ * chan - used when generating a spec file for a channel */ var $_rpm_specname_format = array( - 'pkg' => '%P-%v.spec', + 'pkg' => '%P.spec', 'chan' => 'php-channel-%c.spec' ); @@ -182,22 +189,30 @@ * need to be listed here */ var $_file_prefixes = array( - 'php' => '%{_libdir}/php/pear', + 'php' => '%{php_pear_dir}', 'doc' => '', - 'ext' => '%{_libdir}/php', - 'test' => '%{_libdir}/php/tests/%s', - 'data' => '%{_libdir}/php/data/%s', + 'ext' => '%{%php_extensiondir}', + 'test' => '%{php_pear_dir}/tests/%s', + 'data' => '%{php_pear_dir}/data/%s', 'script' => '%{_bindir}', 'cfg' => '%{_sysconfdir}/pear', 'www' => '%{_datadir}/pear/www' ); + + /** + * Role packages to use for non-standard file roles. Used when generating + * specs for packages only. + */ + var $_role_packages = array( + 'horde' => 'php-horde-Horde_Role', + ); /** * The format to use when adding new RPM header lines to the spec file, in * printf format. The first '%s' is the RPM header name followed by a colon, * the second is the header value. */ - var $_spec_line_format = '%s %s'; + var $_spec_line_format = "%s\t%s"; // ------------------------------------------------------------------------ // --- END DISTRIBUTION CONFIG @@ -247,6 +262,7 @@ 'test_dir' => '', 'test_files_statement' => '',// empty string, or list of test files 'www_files_statement' => '', // empty string, or newline-separated list of files with "www" role + '_noautoreq' => '', // no autoreqdep. PLD Linux specific ); // The name of the template spec file to use @@ -330,15 +346,24 @@ // Initialise the RPM package/dep naming format options $this->_initialiseNamingOptions($options); - + // Set the RPM release version if (isset($options['rpm-release'])) { $this->_output['release'] = $options['rpm-release']; } + + // Pass output file in options + if (isset($options['output'])) { + $this->_output['output-file'] = $options['output']; + } + + // PLD Linux specific. need source md5 + $this->_output['tarball'] = $source_file; + $this->_output['tarball_md5'] = md5(file_get_contents($source_file)); // Set the PEAR RPM name for the PEAR core package $this->_output['pear_rpm_name'] = $this->_getRPMName('PEAR', 'pear.php.net', null, 'pkgdep'); - + // If source file ends in ".xml" we assume we are creating an RPM spec // for a channel rather than an actual package if (substr(strtolower($source_file), -4) == '.xml') { @@ -378,13 +403,40 @@ /** * Format an RPM header line to be added to the spec file * @param string $header The name of the RPM header to be added - * @param string $value The contents of the RPM header + * @param mixed $value The contents of the RPM header * @return string */ - function _formatRpmHeader($header, $value) + function _formatRpmHeader($header, $values) + { + // PLD Linux: we want values sorted and each on their line + $values = (array )$values; + sort($values); + $ret = ''; + foreach ($values as $value) { + $ret .= sprintf($this->_spec_line_format, $header . ':', $value) . "\n"; + } + return $ret; + } + + + /* + * Get an version for RPM package. + * + * @param string $version Package version (e.g. '1.2.3RC1') + * @return string Normalized version + */ + function _formatRpmVersion($version) { - return sprintf($this->_spec_line_format, $header . ':', $value); + + // In PLD Linux alpha, beta, rc versions are noted in Release: not Version: tag. + preg_match('/^(?P[0-9.]+)(?P.*)$/', $version, $m); + if ($m['extraversion']) { + $version = "{$m['version']}-0.{$m['extraversion']}"; + } + + return $version; } + /** * Replace a macro in the output spec file @@ -410,16 +462,20 @@ } else { $package_name = null; } - + // Work out the name of the output spec file - $spec_file = $this->_getRPMNameFromFormat( - $this->_rpm_specname_format[$type], - $package_name, - $this->_output['possible_channel'], - $this->_output['channel_alias'], - $this->_output['version'] - ); - + if (isset($this->_output['output-file'])) { + $spec_file = $this->_output['output-file']; + } else { + $spec_file = $this->_getRPMNameFromFormat( + $this->_rpm_specname_format[$type], + $package_name, + $this->_output['possible_channel'], + $this->_output['channel_alias'], + $this->_output['version'] + ); + } + // Write the actual file $wp = fopen($spec_file, 'wb'); if (!$wp) { @@ -457,7 +513,7 @@ $rpmdep = $this->_getRPMName(null, $cf->getName(), $cf->getAlias(), 'chandep'); if (!empty($rpmdep) && $rpmdep != $this->_output['rpm_package']) { - $this->_output['extra_headers'] = $this->_formatRpmHeader('Provides', "$rpmdep") . "\n"; + $this->_output['extra_headers'] = $this->_formatRpmHeader('Provides', $rpmdep) . "\n"; } // Channels don't really have version numbers; this will need to be @@ -564,7 +620,7 @@ // 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['description'] = wordwrap($package_info['description'], 70); $this->_output['summary'] = trim($package_info['summary']); $this->_output['possible_channel'] = $pf->getChannel(); $this->_output['channel_alias'] = $this->_getChannelAlias($pf->getPackage(), $pf->getChannel()); @@ -591,7 +647,7 @@ // Generate the Requires and Conflicts for the RPM if ($pf->getDeps()) { - $this->_generatePackageDeps($pf); + $this->_generatePackageDeps($pf, $package_info['filelist']); } // Hook to support virtual Provides, where the dependency name differs @@ -646,14 +702,24 @@ if (substr($this->_file_prefixes[$role], -2) == '%s') { $this->_output[$macro_name] = str_replace('%s', $pf->getPackage(), $this->_file_prefixes[$role]); } else { + $attr = ''; if ($role == 'cfg') { - $this->_output[$macro_name] = '%config(noreplace) ' . implode("\n%config(noreplace) ", $files); - } else { - $this->_output[$macro_name] = implode("\n", $files); + $attr = '%config(noreplace) %verify(not md5 mtime size) '; + } elseif ($role == 'script') { + $attr = '%attr(755,root,root) '; } + $this->_output[$macro_name] = $attr . implode("\n$attr", $files); } } $this->_output['files'] = trim($this->_output['files']); + + // figure registry file location + if (in_array($this->_output['possible_channel'], $this->_standard_channels)) { + $registry_dir = '%s/.registry/*.reg'; + } else { + $registry_dir = '%s/.registry/.channel.*/*.reg'; + } + $this->_output['registry_files_statement'] = str_replace('%s', $this->_file_prefixes['php'], $registry_dir); // Handle doc files if (isset($file_list['doc'])) { @@ -683,14 +749,13 @@ } - function _generatePackageDeps($pf) + function _generatePackageDeps($pf, $filelist) { - $requires = $conflicts = array(); + $buildrequires = $requires = $conflicts = $suggests = array(); if ($pf->getPackagexmlVersion() == '1.0') { - foreach ($pf->getDeps() as $dep) { - if (isset($dep['optional']) && $dep['optional'] == 'yes') { - continue; - } + $deps = $pf->getDeps(); + foreach ($deps as $dep) { + $optional = isset($dep['optional']) && $dep['optional'] == 'yes'; if (!isset($dep['type']) || $dep['type'] == 'pkg') { $type = 'pkgdep'; @@ -698,8 +763,14 @@ $type = $dep['type']; } - if (!isset($dep['channel'])) $dep['channel'] = null; if (!isset($dep['name'])) $dep['name'] = ''; //e.g. "php" dep + if (!isset($dep['channel'])) { + // we need to figure out channel as pecl packages are might + // be named differently than pear packages. + $chan_alias = $this->_getChannelAlias($dep['name']); + $reg = &$this->config->getRegistry(); + $dep['channel'] = $reg->channelName($chan_alias); + } // $package contains the *dependency name* here, which may or may // not be the same as the package name @@ -725,21 +796,25 @@ if ($dep['rel'] == 'has') { // We use $package as the index to the $requires array to de-duplicate deps. // Note that in the case of duplicate deps, versioned deps will "win" - see several lines down. - $requires[$package] = $package; + if ($optional) { + $suggests[$package] = $package; + } else { + $requires[$package] = $package; + } } elseif ($dep['rel'] == 'not') { $conflicts[] = $package; } elseif ($dep['rel'] == 'ne') { - $conflicts[] = $package . ' = ' . $dep['version']; + $version = $this->_formatRpmVersion($dep['version']); + $conflicts[] = $package . ' = ' . $version; } elseif (isset($trans[$dep['rel']])) { - $requires[$package] = $package . ' ' . $trans[$dep['rel']] . ' ' . $dep['version']; + $version = $this->_formatRpmVersion($dep['version']); + if ($optional) { + $suggests[$package] = $package . ' ' . $trans[$dep['rel']] . ' ' . $version; + } else { + $requires[$package] = $package . ' ' . $trans[$dep['rel']] . ' ' . $version; + } } } - if (count($requires)) { - $this->_output['extra_headers'] .= $this->_formatRpmHeader('Requires', implode(', ', $requires)) . "\n"; - } - if (count($conflicts)) { - $this->_output['extra_headers'] .= $this->_formatRpmHeader('Conflicts', implode(', ', $conflicts)) . "\n"; - } } else { $this->_output['package2xml'] = '2'; // tell the spec to use package2.xml $deps = $pf->getDeps(true); @@ -842,10 +917,10 @@ } } else { if (isset($dep['min'])) { - $requires[$package] = $package . ' >= ' . $dep['min']; + $requires[$package] = $package . ' >= ' . $this->_formatRpmVersion($dep['min']); } if (isset($dep['max'])) { - $requires[$package] = $package . ' <= ' . $dep['max']; + $requires[$package] = $package . ' <= ' . $this->_formatRpmVersion($dep['max']); } if (isset($dep['exclude'])) { $ex = $dep['exclude']; @@ -865,17 +940,125 @@ $tar->popErrorHandling(); if ($a === null || PEAR::isError($a)) { - $this->_output['package2xml'] = ''; // this doesn't have a package.xml version 1.0 - $requires[$this->_output['pear_rpm_name']] = $this->_output['pear_rpm_name'] . ' >= ' . - $deps['required']['pearinstaller']['min']; + $this->_output['package2xml'] = ''; + $version = $this->_formatRpmVersion($deps['required']['pearinstaller']['min']); + // PLD linux hack: include epoch for PEAR package + $version = "1:{$version}"; + $buildrequires[$this->_output['pear_rpm_name']] = $this->_output['pear_rpm_name'] . ' >= ' . $version; } - if (count($requires)) { - $this->_output['extra_headers'] .= $this->_formatRpmHeader('Requires', implode(', ', $requires)) . "\n"; + } + + if (isset($deps['required']['extension'])) { + if (!isset($deps['required']['extension'][0])) { + $deps['required']['extension'] = array($deps['required']['extension']); + } + foreach ((array )$deps['required']['extension'] as $dep) { + if (!isset($dep['channel'])) $dep['channel'] = null; + // $package contains the *dependency name* here, which may or may + // not be the same as the package name + $package = $this->_getRPMName($dep['name'], $dep['channel'], null, 'ext'); + + if (empty($package)) { + continue; + } + + $requires[$package] = $package; + } + } + + if (isset($deps['required']['subpackage'])) { + if (!isset($deps['required']['subpackage'][0])) { + $deps['required']['subpackage'] = array($deps['required']['subpackage']); + } + foreach ($deps['required']['subpackage'] as $dep) { + if (!isset($dep['channel'])) $dep['channel'] = null; + + // $package contains the *dependency name* here, which may or may + // not be the same as the package name + $package = $this->_getRPMName($dep['name'], $dep['channel'], null, 'pkgdep'); + + if (empty($package)) { + continue; + } + + $requires[$package] = $package; + // XXX: should be more complese like above with ranges, etc + } + } + + if (isset($deps['optional']['package'])) { + if (!isset($deps['optional']['package'][0])) { + $deps['optional']['package'] = array($deps['optional']['package']); + } + foreach ($deps['optional']['package'] as $dep) { + if (!isset($dep['channel'])) $dep['channel'] = null; + + // $package contains the *dependency name* here, which may or may + // not be the same as the package name + $package = $this->_getRPMName($dep['name'], $dep['channel'], null, 'pkgdep'); + + if (empty($package)) { + continue; + } + + // suggests are not versioned (makes no sense in poldek) + $suggests[$package] = $package; + + // PLD Linux: Fill extra info for _noautoreq deps + $this->_output['_noautoreq'] .= " pear(". str_replace('_', '/', $dep['name']) . ".*)"; } - if (count($conflicts)) { - $this->_output['extra_headers'] .= $this->_formatRpmHeader('Conflicts', implode(', ', $conflicts)) . "\n"; + } + + if (isset($deps['optional']['extension'])) { + if (!isset($deps['optional']['extension'][0])) { + $deps['optional']['extension'] = array($deps['optional']['extension']); + } + foreach ($deps['optional']['extension'] as $dep) { + if (!isset($dep['channel'])) $dep['channel'] = null; + + // $package contains the *dependency name* here, which may or may + // not be the same as the package name + $package = $this->_getRPMName($dep['name'], $dep['channel'], null, 'ext'); + + if (empty($package)) { + continue; + } + + // suggests are not versioned (makes no sense in poldek) + $suggests[$package] = $package; } } } + + // go over filelist, to see if we need custom Role package presence + foreach ($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; + } + $role = $attr['role']; + + if (!isset($this->_file_prefixes[$role])) { + if (isset($this->_role_packages[$role])) { + $pkg = $this->_role_packages[$role]; + $buildrequires[$pkg] = $pkg; + } + // TODO: else use some rpm virtual provides for role? + } + } + + // append extra headers which we collected + if (count($buildrequires)) { + $this->_output['extra_headers'] .= $this->_formatRpmHeader('BuildRequires', $buildrequires) . "\n"; + } + if (count($requires)) { + $this->_output['extra_headers'] .= $this->_formatRpmHeader('Requires', $requires) . "\n"; + } + if (count($conflicts)) { + $this->_output['extra_headers'] .= $this->_formatRpmHeader('Conflicts', $conflicts) . "\n"; + } + if (count($suggests)) { + $this->_output['extra_headers'] .= $this->_formatRpmHeader('Suggests', $suggests) . "\n"; + } } @@ -927,9 +1110,21 @@ case 'pkg': return $this->_getRPMNameFromFormat($this->_rpm_pkgname_format['pkg'], $package_name, $chan_name, $chan_alias); case 'pkgdep': - $type = 'pkg'; + // PLD Linux: pecl extensions have different naming format + if ($chan_alias == 'PECL') { + $type = 'pecl-ext'; + } elseif ($chan_alias == 'PEAR') { + $type = 'pear-pkg'; + } else { + $type = 'pkg'; + } // let it drop through... default: + // PLD Linux: sanitize gtk2 ext name. + // http://bugs.php.net/bug.php?id=52663 + if ($type == 'ext' && $package_name == 'php-gtk') { + $package_name = 'gtk2'; + } if (isset($this->_rpm_depname_format[$type]) && !empty($this->_rpm_depname_format[$type])) { return $this->_getRPMNameFromFormat($this->_rpm_depname_format[$type], $package_name, $chan_name, $chan_alias); }