3 * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
4 * sign, makerpm, convert commands)
10 * @author Stig Bakken <ssb@php.net>
11 * @author Martin Jansen <mj@php.net>
12 * @author Greg Beaver <cellog@php.net>
13 * @copyright 1997-2009 The Authors
14 * @license http://opensource.org/licenses/bsd-license.php New BSD License
15 * @version CVS: $Id: Package.php 313024 2011-07-06 19:51:24Z dufuz $
16 * @link http://pear.php.net/package/PEAR
17 * @since File available since Release 0.1
23 require_once 'PEAR/Command/Common.php';
26 * PEAR commands for login/logout
30 * @author Stig Bakken <ssb@php.net>
31 * @author Martin Jansen <mj@php.net>
32 * @author Greg Beaver <cellog@php.net>
33 * @copyright 1997-2009 The Authors
34 * @license http://opensource.org/licenses/bsd-license.php New BSD License
35 * @version Release: @package_version@
36 * @link http://pear.php.net/package/PEAR
37 * @since Class available since Release 0.1
40 class PEAR_Command_Package extends PEAR_Command_Common
42 var $commands = array(
44 'summary' => 'Build Package',
45 'function' => 'doPackage',
48 'nocompress' => array(
50 'doc' => 'Do not gzip the package file'
54 'doc' => 'Print the name of the packaged file.',
57 'doc' => '[descfile] [descfile2]
58 Creates a PEAR package from its description file (usually called
59 package.xml). If a second packagefile is passed in, then
60 the packager will check to make sure that one is a package.xml
61 version 1.0, and the other is a package.xml version 2.0. The
62 package.xml version 1.0 will be saved as "package.xml" in the archive,
63 and the other as "package2.xml" in the archive"
66 'package-validate' => array(
67 'summary' => 'Validate Package Consistency',
68 'function' => 'doPackageValidate',
75 'summary' => 'Run a "cvs diff" for all files in a package',
76 'function' => 'doCvsDiff',
83 'reallyquiet' => array(
85 'doc' => 'Be really quiet',
89 'doc' => 'Diff against revision of DATE',
94 'doc' => 'Diff against tag for package release REL',
99 'doc' => 'Diff against revision REV',
104 'doc' => 'Generate context diff',
108 'doc' => 'Generate unified diff',
110 'ignore-case' => array(
112 'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
114 'ignore-whitespace' => array(
116 'doc' => 'Ignore changes in amount of white space',
118 'ignore-blank-lines' => array(
120 'doc' => 'Ignore changes that insert or delete blank lines',
123 'doc' => 'Report only whether the files differ, no details',
127 'doc' => 'Don\'t do anything, just pretend',
130 'doc' => '<package.xml>
131 Compares all the files in a package. Without any options, this
132 command will compare the current code with the last checked-in code.
133 Using the -r or -R option you may compare the current code with that
134 of a specific release.
138 'summary' => 'Set SVN Release Tag',
139 'function' => 'doSvnTag',
148 'doc' => 'Move (slide) tag if it exists',
152 'doc' => 'Remove tag',
156 'doc' => 'Don\'t do anything, just pretend',
159 'doc' => '<package.xml> [files...]
160 Sets a SVN tag on all files in a package. Use this command after you have
161 packaged a distribution tarball with the "package" command to tag what
162 revisions of what files were in that release. If need to fix something
163 after running svntag once, but before the tarball is released to the public,
164 use the "slide" option to move the release tag.
166 to include files (such as a second package.xml, or tests not included in the
167 release), pass them as additional parameters.
171 'summary' => 'Set CVS Release Tag',
172 'function' => 'doCvsTag',
179 'reallyquiet' => array(
181 'doc' => 'Be really quiet',
185 'doc' => 'Move (slide) tag if it exists',
189 'doc' => 'Remove tag',
193 'doc' => 'Don\'t do anything, just pretend',
196 'doc' => '<package.xml> [files...]
197 Sets a CVS tag on all files in a package. Use this command after you have
198 packaged a distribution tarball with the "package" command to tag what
199 revisions of what files were in that release. If need to fix something
200 after running cvstag once, but before the tarball is released to the public,
201 use the "slide" option to move the release tag.
203 to include files (such as a second package.xml, or tests not included in the
204 release), pass them as additional parameters.
207 'package-dependencies' => array(
208 'summary' => 'Show package dependencies',
209 'function' => 'doPackageDependencies',
211 'options' => array(),
212 'doc' => '<package-file> or <package.xml> or <install-package-name>
213 List all dependencies the package has.
214 Can take a tgz / tar file, package.xml or a package name of an installed package.'
217 'summary' => 'Sign a package distribution file',
218 'function' => 'doSign',
223 'doc' => 'Display GnuPG output',
226 'doc' => '<package-file>
227 Signs a package distribution (.tar or .tgz) file with GnuPG.',
230 'summary' => 'Builds an RPM spec file from a PEAR package',
231 'function' => 'doMakeRPM',
234 'spec-template' => array(
237 'doc' => 'Use FILE as RPM spec file template'
239 'rpm-pkgname' => array(
242 'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
243 by the PEAR package name, defaults to "PEAR::%s".',
246 'doc' => '<package-file>
248 Creates an RPM .spec file for wrapping a PEAR package inside an RPM
249 package. Intended to be used from the SPECS directory, with the PEAR
250 package tarball in the SOURCES directory:
252 $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
253 Wrote RPM spec file PEAR::Net_Geo-1.0.spec
254 $ rpm -bb PEAR::Net_Socket-1.0.spec
256 Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
260 'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
261 'function' => 'doConvert',
266 'doc' => 'do not beautify the filelist.',
269 'doc' => '[descfile] [descfile2]
270 Converts a package.xml in 1.0 format into a package.xml
271 in 2.0 format. The new file will be named package2.xml by default,
272 and package.xml will be used as the old file by default.
273 This is not the most intelligent conversion, and should only be
274 used for automated conversion or learning the format.
282 * PEAR_Command_Package constructor.
286 function PEAR_Command_Package(&$ui, &$config)
288 parent::PEAR_Command_Common($ui, $config);
291 function _displayValidationResults($err, $warn, $strict = false)
293 foreach ($err as $e) {
294 $this->output .= "Error: $e\n";
296 foreach ($warn as $w) {
297 $this->output .= "Warning: $w\n";
299 $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
300 sizeof($err), sizeof($warn));
301 if ($strict && count($err) > 0) {
302 $this->output .= "Fix these errors and try again.";
308 function &getPackager()
310 if (!class_exists('PEAR_Packager')) {
311 require_once 'PEAR/Packager.php';
313 $a = &new PEAR_Packager;
317 function &getPackageFile($config, $debug = false)
319 if (!class_exists('PEAR_Common')) {
320 require_once 'PEAR/Common.php';
322 if (!class_exists('PEAR_PackageFile')) {
323 require_once 'PEAR/PackageFile.php';
325 $a = &new PEAR_PackageFile($config, $debug);
326 $common = new PEAR_Common;
327 $common->ui = $this->ui;
328 $a->setLogger($common);
332 function doPackage($command, $options, $params)
335 $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
336 $pkg2 = isset($params[1]) ? $params[1] : null;
337 if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
338 $pkg2 = 'package2.xml';
341 $packager = &$this->getPackager();
342 $compress = empty($options['nocompress']) ? true : false;
343 $result = $packager->package($pkginfofile, $compress, $pkg2);
344 if (PEAR::isError($result)) {
345 return $this->raiseError($result);
348 // Don't want output, only the package file name just created
349 if (isset($options['showname'])) {
350 $this->output = $result;
354 $this->ui->outputData($this->output, $command);
360 function doPackageValidate($command, $options, $params)
363 if (count($params) < 1) {
364 $params[0] = 'package.xml';
367 $obj = &$this->getPackageFile($this->config, $this->_debug);
369 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
370 $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
371 if (PEAR::isError($info)) {
372 $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
374 $archive = $info->getArchiveFile();
375 $tar = &new Archive_Tar($archive);
376 $tar->extract(dirname($info->getPackageFile()));
377 $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
378 $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
379 basename($info->getPackageFile()));
382 PEAR::staticPopErrorHandling();
383 if (PEAR::isError($info)) {
384 return $this->raiseError($info);
388 if ($info->getPackagexmlVersion() == '2.0') {
389 if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
390 $info->flattenFileList();
391 $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
394 $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
397 $err = $warn = array();
398 if ($errors = $info->getValidationWarnings()) {
399 foreach ($errors as $error) {
400 if ($error['level'] == 'warning') {
401 $warn[] = $error['message'];
403 $err[] = $error['message'];
408 $this->_displayValidationResults($err, $warn);
409 $this->ui->outputData($this->output, $command);
413 function doSvnTag($command, $options, $params)
417 if (count($params) < 1) {
418 $help = $this->getHelp($command);
419 return $this->raiseError("$command: missing parameter: $help[0]");
422 $packageFile = realpath($params[0]);
423 $dir = dirname($packageFile);
424 $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
425 $obj = &$this->getPackageFile($this->config, $this->_debug);
426 $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
427 if (PEAR::isError($info)) {
428 return $this->raiseError($info);
431 $err = $warn = array();
432 if (!$info->validate()) {
433 foreach ($info->getValidationWarnings() as $error) {
434 if ($error['level'] == 'warning') {
435 $warn[] = $error['message'];
437 $err[] = $error['message'];
442 if (!$this->_displayValidationResults($err, $warn, true)) {
443 $this->ui->outputData($this->output, $command);
444 return $this->raiseError('SVN tag failed');
447 $version = $info->getVersion();
448 $package = $info->getName();
449 $svntag = "$package-$version";
451 if (isset($options['delete'])) {
452 return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
455 $path = $this->_svnFindPath($packageFile);
457 // Check if there are any modified files
458 $fp = popen('svn st --xml ' . dirname($packageFile), "r");
460 while ($line = fgets($fp, 1024)) {
461 $out .= rtrim($line)."\n";
465 if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
466 $params = array(array(
467 'name' => 'modified',
470 'prompt' => 'You have files in your SVN checkout (' . $path['from'] . ') that have been modified but not commited, do you still want to tag ' . $version . '?',
472 $answers = $this->ui->confirmDialog($params);
474 if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
479 if (isset($options['slide'])) {
480 $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
483 // Check if tag already exists
484 $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
485 $existsCommand = 'svn ls ' . $path['base'] . 'tags/';
487 $fp = popen($existsCommand, "r");
489 while ($line = fgets($fp, 1024)) {
490 $out .= rtrim($line)."\n";
494 if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
495 $this->ui->outputData($this->output, $command);
496 return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
497 } elseif (file_exists($path['local']['base'] . 'tags') === false) {
498 return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
499 } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
500 return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
502 $makeCommand = 'svn mkdir ' . $releaseTag;
503 $this->output .= "+ $makeCommand\n";
504 if (empty($options['dry-run'])) {
505 // We need to create the tag dir.
506 $fp = popen($makeCommand, "r");
508 while ($line = fgets($fp, 1024)) {
509 $out .= rtrim($line)."\n";
512 $this->output .= "$out\n";
517 if (isset($options['quiet'])) {
521 $command .= ' copy --parents ';
523 $dir = dirname($packageFile);
524 $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
525 $files = array_keys($info->getFilelist());
526 if (!in_array(basename($packageFile), $files)) {
527 $files[] = basename($packageFile);
530 array_shift($params);
531 if (count($params)) {
532 // add in additional files to be tagged (package files and such)
533 $files = array_merge($files, $params);
537 foreach ($files as $file) {
538 if (!file_exists($file)) {
539 $file = $dir . DIRECTORY_SEPARATOR . $file;
541 $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
542 escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
545 $this->output .= implode("\n", $commands) . "\n";
546 if (empty($options['dry-run'])) {
547 foreach ($commands as $command) {
548 $fp = popen($command, "r");
549 while ($line = fgets($fp, 1024)) {
550 $this->output .= rtrim($line)."\n";
556 $command = 'svn ci -m "Tagging the ' . $version . ' release" ' . $releaseTag . "\n";
557 $this->output .= "+ $command\n";
558 if (empty($options['dry-run'])) {
559 $fp = popen($command, "r");
560 while ($line = fgets($fp, 1024)) {
561 $this->output .= rtrim($line)."\n";
566 $this->ui->outputData($this->output, $_cmd);
570 function _svnFindPath($file)
573 $command = "svn info --xml $file";
574 $fp = popen($command, "r");
575 while ($line = fgets($fp, 1024)) {
576 $xml .= rtrim($line)."\n";
579 $url_tag = strpos($xml, '<url>');
580 $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));
583 $path['from'] = substr($url, 0, strrpos($url, '/'));
584 $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);
586 // Figure out the local paths - see http://pear.php.net/bugs/17463
587 $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
588 if ($pos === false) {
589 $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
591 $path['local']['base'] = substr($file, 0, $pos + 1);
596 function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
600 if (isset($options['quiet'])) {
604 $command .= ' remove';
605 $command .= ' -m "Removing tag for the ' . $version . ' release."';
607 $path = $this->_svnFindPath($packageFile);
608 $command .= ' ' . $path['base'] . 'tags/' . $tag;
611 if ($this->config->get('verbose') > 1) {
612 $this->output .= "+ $command\n";
615 $this->output .= "+ $command\n";
616 if (empty($options['dry-run'])) {
617 $fp = popen($command, "r");
618 while ($line = fgets($fp, 1024)) {
619 $this->output .= rtrim($line)."\n";
624 $this->ui->outputData($this->output, $command);
628 function doCvsTag($command, $options, $params)
632 if (count($params) < 1) {
633 $help = $this->getHelp($command);
634 return $this->raiseError("$command: missing parameter: $help[0]");
637 $packageFile = realpath($params[0]);
638 $obj = &$this->getPackageFile($this->config, $this->_debug);
639 $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
640 if (PEAR::isError($info)) {
641 return $this->raiseError($info);
644 $err = $warn = array();
645 if (!$info->validate()) {
646 foreach ($info->getValidationWarnings() as $error) {
647 if ($error['level'] == 'warning') {
648 $warn[] = $error['message'];
650 $err[] = $error['message'];
655 if (!$this->_displayValidationResults($err, $warn, true)) {
656 $this->ui->outputData($this->output, $command);
657 return $this->raiseError('CVS tag failed');
660 $version = $info->getVersion();
661 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
662 $cvstag = "RELEASE_$cvsversion";
663 $files = array_keys($info->getFilelist());
665 if (isset($options['quiet'])) {
669 if (isset($options['reallyquiet'])) {
674 if (isset($options['slide'])) {
678 if (isset($options['delete'])) {
682 $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
683 array_shift($params);
684 if (count($params)) {
685 // add in additional files to be tagged
686 $files = array_merge($files, $params);
689 $dir = dirname($packageFile);
690 $dir = substr($dir, strrpos($dir, '/') + 1);
691 foreach ($files as $file) {
692 if (!file_exists($file)) {
693 $file = $dir . DIRECTORY_SEPARATOR . $file;
695 $command .= ' ' . escapeshellarg($file);
698 if ($this->config->get('verbose') > 1) {
699 $this->output .= "+ $command\n";
702 $this->output .= "+ $command\n";
703 if (empty($options['dry-run'])) {
704 $fp = popen($command, "r");
705 while ($line = fgets($fp, 1024)) {
706 $this->output .= rtrim($line)."\n";
711 $this->ui->outputData($this->output, $_cmd);
715 function doCvsDiff($command, $options, $params)
718 if (sizeof($params) < 1) {
719 $help = $this->getHelp($command);
720 return $this->raiseError("$command: missing parameter: $help[0]");
723 $file = realpath($params[0]);
724 $obj = &$this->getPackageFile($this->config, $this->_debug);
725 $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
726 if (PEAR::isError($info)) {
727 return $this->raiseError($info);
730 $err = $warn = array();
731 if (!$info->validate()) {
732 foreach ($info->getValidationWarnings() as $error) {
733 if ($error['level'] == 'warning') {
734 $warn[] = $error['message'];
736 $err[] = $error['message'];
741 if (!$this->_displayValidationResults($err, $warn, true)) {
742 $this->ui->outputData($this->output, $command);
743 return $this->raiseError('CVS diff failed');
746 $info1 = $info->getFilelist();
749 if (isset($options['quiet'])) {
751 unset($options['quiet']);
754 if (isset($options['reallyquiet'])) {
756 unset($options['reallyquiet']);
759 if (isset($options['release'])) {
760 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
761 $cvstag = "RELEASE_$cvsversion";
762 $options['revision'] = $cvstag;
763 unset($options['release']);
767 if (isset($options['dry-run'])) {
769 unset($options['dry-run']);
773 // the rest of the options are passed right on to "cvs diff"
774 foreach ($options as $option => $optarg) {
775 $arg = $short = false;
776 if (isset($this->commands[$command]['options'][$option])) {
777 $arg = $this->commands[$command]['options'][$option]['arg'];
778 $short = $this->commands[$command]['options'][$option]['shortopt'];
780 $cmd .= $short ? " -$short" : " --$option";
781 if ($arg && $optarg) {
782 $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
786 foreach ($files as $file) {
787 $cmd .= ' ' . escapeshellarg($file['name']);
790 if ($this->config->get('verbose') > 1) {
791 $this->output .= "+ $cmd\n";
795 $fp = popen($cmd, "r");
796 while ($line = fgets($fp, 1024)) {
797 $this->output .= rtrim($line)."\n";
802 $this->ui->outputData($this->output, $command);
806 function doPackageDependencies($command, $options, $params)
808 // $params[0] -> the PEAR package to list its information
809 if (count($params) !== 1) {
810 return $this->raiseError("bad parameter(s), try \"help $command\"");
813 $obj = &$this->getPackageFile($this->config, $this->_debug);
814 if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
815 $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
817 $reg = $this->config->getRegistry();
818 $info = $obj->fromArray($reg->packageInfo($params[0]));
821 if (PEAR::isError($info)) {
822 return $this->raiseError($info);
825 $deps = $info->getDeps();
826 if (is_array($deps)) {
827 if ($info->getPackagexmlVersion() == '1.0') {
829 'caption' => 'Dependencies for pear/' . $info->getPackage(),
831 'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
834 foreach ($deps as $d) {
835 if (isset($d['optional'])) {
836 if ($d['optional'] == 'yes') {
845 if (isset($this->_deps_rel_trans[$d['rel']])) {
846 $rel = $this->_deps_rel_trans[$d['rel']];
851 if (isset($this->_deps_type_trans[$d['type']])) {
852 $type = ucfirst($this->_deps_type_trans[$d['type']]);
857 if (isset($d['name'])) {
863 if (isset($d['version'])) {
864 $version = $d['version'];
869 $data['data'][] = array($req, $type, $name, $rel, $version);
871 } else { // package.xml 2.0 dependencies display
872 require_once 'PEAR/Dependency2.php';
873 $deps = $info->getDependencies();
874 $reg = &$this->config->getRegistry();
875 if (is_array($deps)) {
876 $d = new PEAR_Dependency2($this->config, array(), '');
878 'caption' => 'Dependencies for ' . $info->getPackage(),
880 'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
882 foreach ($deps as $type => $subd) {
883 $req = ($type == 'required') ? 'Yes' : 'No';
884 if ($type == 'group') {
885 $group = $subd['attribs']['name'];
890 if (!isset($subd[0])) {
891 $subd = array($subd);
894 foreach ($subd as $groupa) {
895 foreach ($groupa as $deptype => $depinfo) {
896 if ($deptype == 'attribs') {
900 if ($deptype == 'pearinstaller') {
901 $deptype = 'pear Installer';
904 if (!isset($depinfo[0])) {
905 $depinfo = array($depinfo);
908 foreach ($depinfo as $inf) {
910 if (isset($inf['channel'])) {
911 $alias = $reg->channelAlias($inf['channel']);
913 $alias = '(channel?) ' .$inf['channel'];
915 $name = $alias . '/';
918 if (isset($inf['name'])) {
919 $name .= $inf['name'];
920 } elseif (isset($inf['pattern'])) {
921 $name .= $inf['pattern'];
926 if (isset($inf['uri'])) {
927 $name .= ' [' . $inf['uri'] . ']';
930 if (isset($inf['conflicts'])) {
933 $ver = $d->_getExtraString($inf);
936 $data['data'][] = array($req, ucfirst($deptype), $name,
945 $this->ui->outputData($data, $command);
950 $this->ui->outputData("This package does not have any dependencies.", $command);
953 function doSign($command, $options, $params)
955 // should move most of this code into PEAR_Packager
956 // so it'll be easy to implement "pear package --sign"
957 if (count($params) !== 1) {
958 return $this->raiseError("bad parameter(s), try \"help $command\"");
961 require_once 'System.php';
962 require_once 'Archive/Tar.php';
964 if (!file_exists($params[0])) {
965 return $this->raiseError("file does not exist: $params[0]");
968 $obj = $this->getPackageFile($this->config, $this->_debug);
969 $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
970 if (PEAR::isError($info)) {
971 return $this->raiseError($info);
974 $tar = new Archive_Tar($params[0]);
976 $tmpdir = $this->config->get('temp_dir');
977 $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
978 if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
979 return $this->raiseError("failed to extract tar file");
982 if (file_exists("$tmpdir/package.sig")) {
983 return $this->raiseError("package already signed");
986 $packagexml = 'package.xml';
987 if (file_exists("$tmpdir/package2.xml")) {
988 $packagexml = 'package2.xml';
991 if (file_exists("$tmpdir/package.sig")) {
992 unlink("$tmpdir/package.sig");
995 if (!file_exists("$tmpdir/$packagexml")) {
996 return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
999 $input = $this->ui->userDialog($command,
1000 array('GnuPG Passphrase'),
1002 if (!isset($input[0])) {
1003 //use empty passphrase
1007 $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
1008 $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
1010 return $this->raiseError("gpg command failed");
1013 fwrite($gpg, "$input[0]\n");
1014 if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
1015 return $this->raiseError("gpg sign failed");
1018 if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
1019 return $this->raiseError('failed adding signature to file');
1022 $this->ui->outputData("Package signed.", $command);
1027 * For unit testing purposes
1029 function &getInstaller(&$ui)
1031 if (!class_exists('PEAR_Installer')) {
1032 require_once 'PEAR/Installer.php';
1034 $a = &new PEAR_Installer($ui);
1039 * For unit testing purposes
1041 function &getCommandPackaging(&$ui, &$config)
1043 if (!class_exists('PEAR_Command_Packaging')) {
1044 if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
1046 include_once 'PEAR/Command/Packaging.php';
1050 if (class_exists('PEAR_Command_Packaging')) {
1051 $a = &new PEAR_Command_Packaging($ui, $config);
1059 function doMakeRPM($command, $options, $params)
1062 // Check to see if PEAR_Command_Packaging is installed, and
1063 // transparently switch to use the "make-rpm-spec" command from it
1064 // instead, if it does. Otherwise, continue to use the old version
1065 // of "makerpm" supplied with this package (PEAR).
1066 $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
1067 if ($packaging_cmd !== null) {
1068 $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
1069 'newer "make-rpm-spec" command instead');
1070 return $packaging_cmd->run('make-rpm-spec', $options, $params);
1073 $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
1074 'improved version is available via "pear make-rpm-spec", which '.
1075 'is available by installing PEAR_Command_Packaging');
1079 function doConvert($command, $options, $params)
1081 $packagexml = isset($params[0]) ? $params[0] : 'package.xml';
1082 $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
1083 DIRECTORY_SEPARATOR . 'package2.xml';
1084 $pkg = &$this->getPackageFile($this->config, $this->_debug);
1085 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1086 $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
1087 PEAR::staticPopErrorHandling();
1088 if (PEAR::isError($pf)) {
1089 if (is_array($pf->getUserInfo())) {
1090 foreach ($pf->getUserInfo() as $warning) {
1091 $this->ui->outputData($warning['message']);
1094 return $this->raiseError($pf);
1097 if (is_a($pf, 'PEAR_PackageFile_v2')) {
1098 $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
1102 $gen = &$pf->getDefaultGenerator();
1103 $newpf = &$gen->toV2();
1104 $newpf->setPackagefile($newpackagexml);
1105 $gen = &$newpf->getDefaultGenerator();
1106 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1107 $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
1108 $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
1109 PEAR::staticPopErrorHandling();
1110 if (PEAR::isError($saved)) {
1111 if (is_array($saved->getUserInfo())) {
1112 foreach ($saved->getUserInfo() as $warning) {
1113 $this->ui->outputData($warning['message']);
1117 $this->ui->outputData($saved->getMessage());
1121 $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');