PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file Package.php

Documentation is available at Package.php

  1. <?php
  2. /**
  3.  * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
  4.  * sign, makerpm, convert commands)
  5.  *
  6.  * PHP versions 4 and 5
  7.  *
  8.  * @category   pear
  9.  * @package    PEAR
  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
  18.  */
  19.  
  20. /**
  21.  * base class
  22.  */
  23. require_once 'PEAR/Command/Common.php';
  24.  
  25. /**
  26.  * PEAR commands for login/logout
  27.  *
  28.  * @category   pear
  29.  * @package    PEAR
  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
  38.  */
  39.  
  40. {
  41.     var $commands = array(
  42.         'package' => array(
  43.             'summary' => 'Build Package',
  44.             'function' => 'doPackage',
  45.             'shortcut' => 'p',
  46.             'options' => array(
  47.                 'nocompress' => array(
  48.                     'shortopt' => 'Z',
  49.                     'doc' => 'Do not gzip the package file'
  50.                     ),
  51.                 'showname' => array(
  52.                     'shortopt' => 'n',
  53.                     'doc' => 'Print the name of the packaged file.',
  54.                     ),
  55.                 ),
  56.             'doc' => '[descfile] [descfile2]
  57. Creates a PEAR package from its description file (usually called
  58. package.xml).  If a second packagefile is passed in, then
  59. the packager will check to make sure that one is a package.xml
  60. version 1.0, and the other is a package.xml version 2.0.  The
  61. package.xml version 1.0 will be saved as "package.xml" in the archive,
  62. and the other as "package2.xml" in the archive"
  63. '
  64.             ),
  65.         'package-validate' => array(
  66.             'summary' => 'Validate Package Consistency',
  67.             'function' => 'doPackageValidate',
  68.             'shortcut' => 'pv',
  69.             'options' => array(),
  70.             'doc' => '
  71. ',
  72.             ),
  73.         'cvsdiff' => array(
  74.             'summary' => 'Run a "cvs diff" for all files in a package',
  75.             'function' => 'doCvsDiff',
  76.             'shortcut' => 'cd',
  77.             'options' => array(
  78.                 'quiet' => array(
  79.                     'shortopt' => 'q',
  80.                     'doc' => 'Be quiet',
  81.                     ),
  82.                 'reallyquiet' => array(
  83.                     'shortopt' => 'Q',
  84.                     'doc' => 'Be really quiet',
  85.                     ),
  86.                 'date' => array(
  87.                     'shortopt' => 'D',
  88.                     'doc' => 'Diff against revision of DATE',
  89.                     'arg' => 'DATE',
  90.                     ),
  91.                 'release' => array(
  92.                     'shortopt' => 'R',
  93.                     'doc' => 'Diff against tag for package release REL',
  94.                     'arg' => 'REL',
  95.                     ),
  96.                 'revision' => array(
  97.                     'shortopt' => 'r',
  98.                     'doc' => 'Diff against revision REV',
  99.                     'arg' => 'REV',
  100.                     ),
  101.                 'context' => array(
  102.                     'shortopt' => 'c',
  103.                     'doc' => 'Generate context diff',
  104.                     ),
  105.                 'unified' => array(
  106.                     'shortopt' => 'u',
  107.                     'doc' => 'Generate unified diff',
  108.                     ),
  109.                 'ignore-case' => array(
  110.                     'shortopt' => 'i',
  111.                     'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
  112.                     ),
  113.                 'ignore-whitespace' => array(
  114.                     'shortopt' => 'b',
  115.                     'doc' => 'Ignore changes in amount of white space',
  116.                     ),
  117.                 'ignore-blank-lines' => array(
  118.                     'shortopt' => 'B',
  119.                     'doc' => 'Ignore changes that insert or delete blank lines',
  120.                     ),
  121.                 'brief' => array(
  122.                     'doc' => 'Report only whether the files differ, no details',
  123.                     ),
  124.                 'dry-run' => array(
  125.                     'shortopt' => 'n',
  126.                     'doc' => 'Don\'t do anything, just pretend',
  127.                     ),
  128.                 ),
  129.             'doc' => '<package.xml>
  130. Compares all the files in a package.  Without any options, this
  131. command will compare the current code with the last checked-in code.
  132. Using the -r or -R option you may compare the current code with that
  133. of a specific release.
  134. ',
  135.             ),
  136.          'svntag' => array(
  137.              'summary' => 'Set SVN Release Tag',
  138.              'function' => 'doSvnTag',
  139.              'shortcut' => 'sv',
  140.              'options' => array(
  141.                  'quiet' => array(
  142.                      'shortopt' => 'q',
  143.                      'doc' => 'Be quiet',
  144.                      ),
  145.                  'slide' => array(
  146.                      'shortopt' => 'F',
  147.                      'doc' => 'Move (slide) tag if it exists',
  148.                      ),
  149.                  'delete' => array(
  150.                      'shortopt' => 'd',
  151.                      'doc' => 'Remove tag',
  152.                      ),
  153.                  'dry-run' => array(
  154.                      'shortopt' => 'n',
  155.                      'doc' => 'Don\'t do anything, just pretend',
  156.                      ),
  157.                  ),
  158.              'doc' => '<package.xml> [files...]
  159.  Sets a SVN tag on all files in a package.  Use this command after you have
  160.  packaged a distribution tarball with the "package" command to tag what
  161.  revisions of what files were in that release.  If need to fix something
  162.  after running svntag once, but before the tarball is released to the public,
  163.  use the "slide" option to move the release tag.
  164.  
  165.  to include files (such as a second package.xml, or tests not included in the
  166.  release), pass them as additional parameters.
  167.  ',
  168.              ),
  169.         'cvstag' => array(
  170.             'summary' => 'Set CVS Release Tag',
  171.             'function' => 'doCvsTag',
  172.             'shortcut' => 'ct',
  173.             'options' => array(
  174.                 'quiet' => array(
  175.                     'shortopt' => 'q',
  176.                     'doc' => 'Be quiet',
  177.                     ),
  178.                 'reallyquiet' => array(
  179.                     'shortopt' => 'Q',
  180.                     'doc' => 'Be really quiet',
  181.                     ),
  182.                 'slide' => array(
  183.                     'shortopt' => 'F',
  184.                     'doc' => 'Move (slide) tag if it exists',
  185.                     ),
  186.                 'delete' => array(
  187.                     'shortopt' => 'd',
  188.                     'doc' => 'Remove tag',
  189.                     ),
  190.                 'dry-run' => array(
  191.                     'shortopt' => 'n',
  192.                     'doc' => 'Don\'t do anything, just pretend',
  193.                     ),
  194.                 ),
  195.             'doc' => '<package.xml> [files...]
  196. Sets a CVS tag on all files in a package.  Use this command after you have
  197. packaged a distribution tarball with the "package" command to tag what
  198. revisions of what files were in that release.  If need to fix something
  199. after running cvstag once, but before the tarball is released to the public,
  200. use the "slide" option to move the release tag.
  201.  
  202. to include files (such as a second package.xml, or tests not included in the
  203. release), pass them as additional parameters.
  204. ',
  205.             ),
  206.         'package-dependencies' => array(
  207.             'summary' => 'Show package dependencies',
  208.             'function' => 'doPackageDependencies',
  209.             'shortcut' => 'pd',
  210.             'options' => array(),
  211.             'doc' => '<package-file> or <package.xml> or <install-package-name>
  212. List all dependencies the package has.
  213. Can take a tgz / tar file, package.xml or a package name of an installed package.'
  214.             ),
  215.         'sign' => array(
  216.             'summary' => 'Sign a package distribution file',
  217.             'function' => 'doSign',
  218.             'shortcut' => 'si',
  219.             'options' => array(
  220.                 'verbose' => array(
  221.                     'shortopt' => 'v',
  222.                     'doc' => 'Display GnuPG output',
  223.                     ),
  224.             ),
  225.             'doc' => '<package-file>
  226. Signs a package distribution (.tar or .tgz) file with GnuPG.',
  227.             ),
  228.         'makerpm' => array(
  229.             'summary' => 'Builds an RPM spec file from a PEAR package',
  230.             'function' => 'doMakeRPM',
  231.             'shortcut' => 'rpm',
  232.             'options' => array(
  233.                 'spec-template' => array(
  234.                     'shortopt' => 't',
  235.                     'arg' => 'FILE',
  236.                     'doc' => 'Use FILE as RPM spec file template'
  237.                     ),
  238.                 'rpm-pkgname' => array(
  239.                     'shortopt' => 'p',
  240.                     'arg' => 'FORMAT',
  241.                     'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
  242. by the PEAR package name, defaults to "PEAR::%s".',
  243.                     ),
  244.                 ),
  245.             'doc' => '<package-file>
  246.  
  247. Creates an RPM .spec file for wrapping a PEAR package inside an RPM
  248. package.  Intended to be used from the SPECS directory, with the PEAR
  249. package tarball in the SOURCES directory:
  250.  
  251. $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
  252. Wrote RPM spec file PEAR::Net_Geo-1.0.spec
  253. $ rpm -bb PEAR::Net_Socket-1.0.spec
  254. ...
  255. Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
  256. ',
  257.             ),
  258.         'convert' => array(
  259.             'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
  260.             'function' => 'doConvert',
  261.             'shortcut' => 'c2',
  262.             'options' => array(
  263.                 'flat' => array(
  264.                     'shortopt' => 'f',
  265.                     'doc' => 'do not beautify the filelist.',
  266.                     ),
  267.                 ),
  268.             'doc' => '[descfile] [descfile2]
  269. Converts a package.xml in 1.0 format into a package.xml
  270. in 2.0 format.  The new file will be named package2.xml by default,
  271. and package.xml will be used as the old file by default.
  272. This is not the most intelligent conversion, and should only be
  273. used for automated conversion or learning the format.
  274. '
  275.             ),
  276.         );
  277.  
  278.     var $output;
  279.  
  280.     /**
  281.      * PEAR_Command_Package constructor.
  282.      *
  283.      * @access public
  284.      */
  285.     function PEAR_Command_Package(&$ui&$config)
  286.     {
  287.         parent::PEAR_Command_Common($ui$config);
  288.     }
  289.  
  290.     function _displayValidationResults($err$warn$strict = false)
  291.     {
  292.         foreach ($err as $e{
  293.             $this->output .= "Error: $e\n";
  294.         }
  295.         foreach ($warn as $w{
  296.             $this->output .= "Warning: $w\n";
  297.         }
  298.         $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
  299.                                        sizeof($err)sizeof($warn));
  300.         if ($strict && count($err> 0{
  301.             $this->output .= "Fix these errors and try again.";
  302.             return false;
  303.         }
  304.         return true;
  305.     }
  306.  
  307.     function &getPackager()
  308.     {
  309.         if (!class_exists('PEAR_Packager')) {
  310.             require_once 'PEAR/Packager.php';
  311.         }
  312.         $a &new PEAR_Packager;
  313.         return $a;
  314.     }
  315.  
  316.     function &getPackageFile($config$debug = false)
  317.     {
  318.         if (!class_exists('PEAR_Common')) {
  319.             require_once 'PEAR/Common.php';
  320.         }
  321.         if (!class_exists('PEAR_PackageFile')) {
  322.             require_once 'PEAR/PackageFile.php';
  323.         }
  324.         $a &new PEAR_PackageFile($config$debug);
  325.         $common = new PEAR_Common;
  326.         $common->ui = $this->ui;
  327.         $a->setLogger($common);
  328.         return $a;
  329.     }
  330.  
  331.     function doPackage($command$options$params)
  332.     {
  333.         $this->output = '';
  334.         $pkginfofile = isset($params[0]$params[0'package.xml';
  335.         $pkg2 = isset($params[1]$params[1: null;
  336.         if (!$pkg2 && !isset($params[0]&& file_exists('package2.xml')) {
  337.             $pkg2 'package2.xml';
  338.         }
  339.  
  340.         $packager &$this->getPackager();
  341.         $compress = empty($options['nocompress']? true : false;
  342.         $result   $packager->package($pkginfofile$compress$pkg2);
  343.         if (PEAR::isError($result)) {
  344.             return $this->raiseError($result);
  345.         }
  346.  
  347.         // Don't want output, only the package file name just created
  348.         if (isset($options['showname'])) {
  349.             $this->output = $result;
  350.         }
  351.  
  352.         if ($this->output{
  353.             $this->ui->outputData($this->output$command);
  354.         }
  355.  
  356.         return true;
  357.     }
  358.  
  359.     function doPackageValidate($command$options$params)
  360.     {
  361.         $this->output = '';
  362.         if (count($params< 1{
  363.             $params[0'package.xml';
  364.         }
  365.  
  366.         $obj &$this->getPackageFile($this->config$this->_debug);
  367.         $obj->rawReturn();
  368.         $info $obj->fromTgzFile($params[0]PEAR_VALIDATE_NORMAL);
  369.         if (PEAR::isError($info)) {
  370.             $info $obj->fromPackageFile($params[0]PEAR_VALIDATE_NORMAL);
  371.         else {
  372.             $archive $info->getArchiveFile();
  373.             $tar &new Archive_Tar($archive);
  374.             $tar->extract(dirname($info->getPackageFile()));
  375.             $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
  376.                 $info->getPackage('-' $info->getVersion(. DIRECTORY_SEPARATOR .
  377.                 basename($info->getPackageFile()));
  378.         }
  379.  
  380.         PEAR::staticPopErrorHandling();
  381.         if (PEAR::isError($info)) {
  382.             return $this->raiseError($info);
  383.         }
  384.  
  385.         $valid = false;
  386.         if ($info->getPackagexmlVersion(== '2.0'{
  387.             if ($valid $info->validate(PEAR_VALIDATE_NORMAL)) {
  388.                 $info->flattenFileList();
  389.                 $valid $info->validate(PEAR_VALIDATE_PACKAGING);
  390.             }
  391.         else {
  392.             $valid $info->validate(PEAR_VALIDATE_PACKAGING);
  393.         }
  394.  
  395.         $err $warn = array();
  396.         if ($errors $info->getValidationWarnings()) {
  397.             foreach ($errors as $error{
  398.                 if ($error['level'== 'warning'{
  399.                     $warn[$error['message'];
  400.                 else {
  401.                     $err[$error['message'];
  402.                 }
  403.             }
  404.         }
  405.  
  406.         $this->_displayValidationResults($err$warn);
  407.         $this->ui->outputData($this->output$command);
  408.         return true;
  409.     }
  410.  
  411.     function doSvnTag($command$options$params)
  412.     {
  413.         $this->output = '';
  414.         $_cmd $command;
  415.         if (count($params< 1{
  416.             $help $this->getHelp($command);
  417.             return $this->raiseError("$command: missing parameter: $help[0]");
  418.         }
  419.  
  420.         $packageFile realpath($params[0]);
  421.         $dir dirname($packageFile);
  422.         $dir substr($dirstrrpos($dirDIRECTORY_SEPARATOR+ 1);
  423.         $obj  &$this->getPackageFile($this->config$this->_debug);
  424.         $info $obj->fromAnyFile($packageFilePEAR_VALIDATE_NORMAL);
  425.         if (PEAR::isError($info)) {
  426.             return $this->raiseError($info);
  427.         }
  428.  
  429.         $err $warn = array();
  430.         if (!$info->validate()) {
  431.             foreach ($info->getValidationWarnings(as $error{
  432.                 if ($error['level'== 'warning'{
  433.                     $warn[$error['message'];
  434.                 else {
  435.                     $err[$error['message'];
  436.                 }
  437.             }
  438.         }
  439.  
  440.         if (!$this->_displayValidationResults($err$warntrue)) {
  441.             $this->ui->outputData($this->output$command);
  442.             return $this->raiseError('SVN tag failed');
  443.         }
  444.  
  445.         $version    $info->getVersion();
  446.         $package    $info->getName();
  447.         $svntag     = "$package-$version";
  448.  
  449.         if (isset($options['delete'])) {
  450.             return $this->_svnRemoveTag($version$package$svntag$packageFile$options);
  451.         }
  452.  
  453.         $path $this->_svnFindPath($packageFile);
  454.  
  455.         // Check if there are any modified files
  456.         $fp popen('svn st --xml ' dirname($packageFile)"r");
  457.         $out '';
  458.         while ($line fgets($fp1024)) {
  459.             $out .= rtrim($line)."\n";
  460.         }
  461.         pclose($fp);
  462.  
  463.         if (!isset($options['quiet']&& strpos($out'item="modified"')) {
  464.             $params = array(array(
  465.                 'name' => 'modified',
  466.                 'type' => 'yesno',
  467.                 'default' => 'no',
  468.                 'prompt' => 'You have files in your SVN checkout (' $path['from']  ') that have been modified but not commited, do you still want to tag ' $version '?',
  469.             ));
  470.             $answers $this->ui->confirmDialog($params);
  471.  
  472.             if (!in_array($answers['modified']array('y''yes''on''1'))) {
  473.                 return true;
  474.             }
  475.         }
  476.  
  477.         if (isset($options['slide'])) {
  478.             $this->_svnRemoveTag($version$package$svntag$packageFile$options);
  479.         }
  480.  
  481.         // Check if tag already exists
  482.         $releaseTag $path['local']['base''tags' . DIRECTORY_SEPARATOR . $svntag;
  483.         $existsCommand 'svn ls ' $path['base''tags/';
  484.  
  485.         $fp popen($existsCommand"r");
  486.         $out '';
  487.         while ($line fgets($fp1024)) {
  488.             $out .= rtrim($line)."\n";
  489.         }
  490.         pclose($fp);
  491.  
  492.         if (in_array($svntag . DIRECTORY_SEPARATORexplode("\n"$out))) {
  493.             $this->ui->outputData($this->output$command);
  494.             return $this->raiseError('SVN tag ' $svntag ' for ' $package ' already exists.');
  495.         elseif (file_exists($path['local']['base''tags'=== false{
  496.             return $this->raiseError('Can not locate the tags directory at ' $path['local']['base''tags');
  497.         elseif (is_writeable($path['local']['base''tags'=== false{
  498.             return $this->raiseError('Can not write to the tag directory at ' $path['local']['base''tags');
  499.         else {
  500.             $makeCommand 'svn mkdir ' $releaseTag;
  501.             $this->output .= "$makeCommand\n";
  502.             if (empty($options['dry-run'])) {
  503.                 // We need to create the tag dir.
  504.                 $fp popen($makeCommand"r");
  505.                 $out '';
  506.                 while ($line fgets($fp1024)) {
  507.                     $out .= rtrim($line)."\n";
  508.                 }
  509.                 pclose($fp);
  510.                 $this->output .= "$out\n";
  511.             }
  512.         }
  513.  
  514.         $command 'svn';
  515.         if (isset($options['quiet'])) {
  516.             $command .= ' -q';
  517.         }
  518.  
  519.         $command .= ' copy --parents ';
  520.  
  521.         $dir   dirname($packageFile);
  522.         $dir   substr($dirstrrpos($dirDIRECTORY_SEPARATOR+ 1);
  523.         $files array_keys($info->getFilelist());
  524.         if (!in_array(basename($packageFile)$files)) {
  525.             $files[basename($packageFile);
  526.         }
  527.  
  528.         array_shift($params);
  529.         if (count($params)) {
  530.             // add in additional files to be tagged (package files and such)
  531.             $files array_merge($files$params);
  532.         }
  533.  
  534.         $commands = array();
  535.         foreach ($files as $file{
  536.             if (!file_exists($file)) {
  537.                 $file $dir . DIRECTORY_SEPARATOR . $file;
  538.             }
  539.             $commands[$command ' ' escapeshellarg($file' ' .
  540.                           escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
  541.         }
  542.  
  543.         $this->output .= implode("\n"$commands"\n";
  544.         if (empty($options['dry-run'])) {
  545.             foreach ($commands as $command{
  546.                 $fp popen($command"r");
  547.                 while ($line fgets($fp1024)) {
  548.                     $this->output .= rtrim($line)."\n";
  549.                 }
  550.                 pclose($fp);
  551.             }
  552.         }
  553.  
  554.         $command 'svn ci -m "Tagging the ' $version  ' release" ' $releaseTag "\n";
  555.         $this->output .= "$command\n";
  556.         if (empty($options['dry-run'])) {
  557.             $fp popen($command"r");
  558.             while ($line fgets($fp1024)) {
  559.                 $this->output .= rtrim($line)."\n";
  560.             }
  561.             pclose($fp);
  562.         }
  563.  
  564.         $this->ui->outputData($this->output$_cmd);
  565.         return true;
  566.     }
  567.  
  568.     function _svnFindPath($file)
  569.     {
  570.         $xml '';
  571.         $command = "svn info --xml $file";
  572.         $fp popen($command"r");
  573.         while ($line fgets($fp1024)) {
  574.             $xml .= rtrim($line)."\n";
  575.         }
  576.         pclose($fp);
  577.         $url_tag strpos($xml'<url>');
  578.         $url substr($xml$url_tag + 5strpos($xml'</url>'$url_tag + 5($url_tag + 5));
  579.  
  580.         $path = array();
  581.         $path['from'substr($url0strrpos($url'/'));
  582.         $path['base'substr($path['from']0strrpos($path['from']'/'+ 1);
  583.  
  584.         // Figure out the local paths - see http://pear.php.net/bugs/17463
  585.         $pos strpos($fileDIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
  586.         if ($pos === false{
  587.             $pos strpos($fileDIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
  588.         }
  589.         $path['local']['base'substr($file0$pos + 1);
  590.  
  591.         return $path;
  592.     }
  593.  
  594.     function _svnRemoveTag($version$package$tag$packageFile$options)
  595.     {
  596.         $command 'svn';
  597.  
  598.         if (isset($options['quiet'])) {
  599.             $command .= ' -q';
  600.         }
  601.  
  602.         $command .= ' remove';
  603.         $command .= ' -m "Removing tag for the ' $version  ' release."';
  604.  
  605.         $path $this->_svnFindPath($packageFile);
  606.         $command .= ' ' $path['base''tags/' $tag;
  607.  
  608.  
  609.         if ($this->config->get('verbose'> 1{
  610.             $this->output .= "$command\n";
  611.         }
  612.  
  613.         $this->output .= "$command\n";
  614.         if (empty($options['dry-run'])) {
  615.             $fp popen($command"r");
  616.             while ($line fgets($fp1024)) {
  617.                 $this->output .= rtrim($line)."\n";
  618.             }
  619.             pclose($fp);
  620.         }
  621.  
  622.         $this->ui->outputData($this->output$command);
  623.         return true;
  624.     }
  625.  
  626.     function doCvsTag($command$options$params)
  627.     {
  628.         $this->output = '';
  629.         $_cmd $command;
  630.         if (count($params< 1{
  631.             $help $this->getHelp($command);
  632.             return $this->raiseError("$command: missing parameter: $help[0]");
  633.         }
  634.  
  635.         $packageFile realpath($params[0]);
  636.         $obj  &$this->getPackageFile($this->config$this->_debug);
  637.         $info $obj->fromAnyFile($packageFilePEAR_VALIDATE_NORMAL);
  638.         if (PEAR::isError($info)) {
  639.             return $this->raiseError($info);
  640.         }
  641.  
  642.         $err $warn = array();
  643.         if (!$info->validate()) {
  644.             foreach ($info->getValidationWarnings(as $error{
  645.                 if ($error['level'== 'warning'{
  646.                     $warn[$error['message'];
  647.                 else {
  648.                     $err[$error['message'];
  649.                 }
  650.             }
  651.         }
  652.  
  653.         if (!$this->_displayValidationResults($err$warntrue)) {
  654.             $this->ui->outputData($this->output$command);
  655.             return $this->raiseError('CVS tag failed');
  656.         }
  657.  
  658.         $version    $info->getVersion();
  659.         $cvsversion preg_replace('/[^a-z0-9]/i''_'$version);
  660.         $cvstag     = "RELEASE_$cvsversion";
  661.         $files      array_keys($info->getFilelist());
  662.         $command 'cvs';
  663.         if (isset($options['quiet'])) {
  664.             $command .= ' -q';
  665.         }
  666.  
  667.         if (isset($options['reallyquiet'])) {
  668.             $command .= ' -Q';
  669.         }
  670.  
  671.         $command .= ' tag';
  672.         if (isset($options['slide'])) {
  673.             $command .= ' -F';
  674.         }
  675.  
  676.         if (isset($options['delete'])) {
  677.             $command .= ' -d';
  678.         }
  679.  
  680.         $command .= ' ' $cvstag ' ' escapeshellarg($params[0]);
  681.         array_shift($params);
  682.         if (count($params)) {
  683.             // add in additional files to be tagged
  684.             $files array_merge($files$params);
  685.         }
  686.  
  687.         $dir dirname($packageFile);
  688.         $dir substr($dirstrrpos($dir'/'+ 1);
  689.         foreach ($files as $file{
  690.             if (!file_exists($file)) {
  691.                 $file $dir . DIRECTORY_SEPARATOR . $file;
  692.             }
  693.             $command .= ' ' escapeshellarg($file);
  694.         }
  695.  
  696.         if ($this->config->get('verbose'> 1{
  697.             $this->output .= "$command\n";
  698.         }
  699.  
  700.         $this->output .= "$command\n";
  701.         if (empty($options['dry-run'])) {
  702.             $fp popen($command"r");
  703.             while ($line fgets($fp1024)) {
  704.                 $this->output .= rtrim($line)."\n";
  705.             }
  706.             pclose($fp);
  707.         }
  708.  
  709.         $this->ui->outputData($this->output$_cmd);
  710.         return true;
  711.     }
  712.  
  713.     function doCvsDiff($command$options$params)
  714.     {
  715.         $this->output = '';
  716.         if (sizeof($params< 1{
  717.             $help $this->getHelp($command);
  718.             return $this->raiseError("$command: missing parameter: $help[0]");
  719.         }
  720.  
  721.         $file realpath($params[0]);
  722.         $obj  &$this->getPackageFile($this->config$this->_debug);
  723.         $info $obj->fromAnyFile($filePEAR_VALIDATE_NORMAL);
  724.         if (PEAR::isError($info)) {
  725.             return $this->raiseError($info);
  726.         }
  727.  
  728.         $err $warn = array();
  729.         if (!$info->validate()) {
  730.             foreach ($info->getValidationWarnings(as $error{
  731.                 if ($error['level'== 'warning'{
  732.                     $warn[$error['message'];
  733.                 else {
  734.                     $err[$error['message'];
  735.                 }
  736.             }
  737.         }
  738.  
  739.         if (!$this->_displayValidationResults($err$warntrue)) {
  740.             $this->ui->outputData($this->output$command);
  741.             return $this->raiseError('CVS diff failed');
  742.         }
  743.  
  744.         $info1 $info->getFilelist();
  745.         $files $info1;
  746.         $cmd "cvs";
  747.         if (isset($options['quiet'])) {
  748.             $cmd .= ' -q';
  749.             unset($options['quiet']);
  750.         }
  751.  
  752.         if (isset($options['reallyquiet'])) {
  753.             $cmd .= ' -Q';
  754.             unset($options['reallyquiet']);
  755.         }
  756.  
  757.         if (isset($options['release'])) {
  758.             $cvsversion preg_replace('/[^a-z0-9]/i''_'$options['release']);
  759.             $cvstag = "RELEASE_$cvsversion";
  760.             $options['revision'$cvstag;
  761.             unset($options['release']);
  762.         }
  763.  
  764.         $execute = true;
  765.         if (isset($options['dry-run'])) {
  766.             $execute = false;
  767.             unset($options['dry-run']);
  768.         }
  769.  
  770.         $cmd .= ' diff';
  771.         // the rest of the options are passed right on to "cvs diff"
  772.         foreach ($options as $option => $optarg{
  773.             $arg $short = false;
  774.             if (isset($this->commands[$command]['options'][$option])) {
  775.                 $arg $this->commands[$command]['options'][$option]['arg'];
  776.                 $short $this->commands[$command]['options'][$option]['shortopt'];
  777.             }
  778.             $cmd .= $short ? " -$short" : " --$option";
  779.             if ($arg && $optarg{
  780.                 $cmd .= ($short '' '='escapeshellarg($optarg);
  781.             }
  782.         }
  783.  
  784.         foreach ($files as $file{
  785.             $cmd .= ' ' escapeshellarg($file['name']);
  786.         }
  787.  
  788.         if ($this->config->get('verbose'> 1{
  789.             $this->output .= "$cmd\n";
  790.         }
  791.  
  792.         if ($execute{
  793.             $fp popen($cmd"r");
  794.             while ($line fgets($fp1024)) {
  795.                 $this->output .= rtrim($line)."\n";
  796.             }
  797.             pclose($fp);
  798.         }
  799.  
  800.         $this->ui->outputData($this->output$command);
  801.         return true;
  802.     }
  803.  
  804.     function doPackageDependencies($command$options$params)
  805.     {
  806.         // $params[0] -> the PEAR package to list its information
  807.         if (count($params!== 1{
  808.             return $this->raiseError("bad parameter(s), try \"help $command\"");
  809.         }
  810.  
  811.         $obj &$this->getPackageFile($this->config$this->_debug);
  812.         if (is_file($params[0]|| strpos($params[0]'.xml'> 0{
  813.            $info $obj->fromAnyFile($params[0]PEAR_VALIDATE_NORMAL);
  814.         else {
  815.             $reg  $this->config->getRegistry();
  816.             $info $obj->fromArray($reg->packageInfo($params[0]));
  817.         }
  818.  
  819.         if (PEAR::isError($info)) {
  820.             return $this->raiseError($info);
  821.         }
  822.  
  823.         $deps $info->getDeps();
  824.         if (is_array($deps)) {
  825.             if ($info->getPackagexmlVersion(== '1.0'{
  826.                 $data = array(
  827.                     'caption' => 'Dependencies for pear/' $info->getPackage(),
  828.                     'border' => true,
  829.                     'headline' => array("Required?""Type""Name""Relation""Version"),
  830.                     );
  831.  
  832.                 foreach ($deps as $d{
  833.                     if (isset($d['optional'])) {
  834.                         if ($d['optional'== 'yes'{
  835.                             $req 'No';
  836.                         else {
  837.                             $req 'Yes';
  838.                         }
  839.                     else {
  840.                         $req 'Yes';
  841.                     }
  842.  
  843.                     if (isset($this->_deps_rel_trans[$d['rel']])) {
  844.                         $rel $this->_deps_rel_trans[$d['rel']];
  845.                     else {
  846.                         $rel $d['rel'];
  847.                     }
  848.  
  849.                     if (isset($this->_deps_type_trans[$d['type']])) {
  850.                         $type ucfirst($this->_deps_type_trans[$d['type']]);
  851.                     else {
  852.                         $type $d['type'];
  853.                     }
  854.  
  855.                     if (isset($d['name'])) {
  856.                         $name $d['name'];
  857.                     else {
  858.                         $name '';
  859.                     }
  860.  
  861.                     if (isset($d['version'])) {
  862.                         $version $d['version'];
  863.                     else {
  864.                         $version '';
  865.                     }
  866.  
  867.                     $data['data'][= array($req$type$name$rel$version);
  868.                 }
  869.             else // package.xml 2.0 dependencies display
  870.                 require_once 'PEAR/Dependency2.php';
  871.                 $deps $info->getDependencies();
  872.                 $reg &$this->config->getRegistry();
  873.                 if (is_array($deps)) {
  874.                     $d = new PEAR_Dependency2($this->configarray()'');
  875.                     $data = array(
  876.                         'caption' => 'Dependencies for ' $info->getPackage(),
  877.                         'border' => true,
  878.                         'headline' => array("Required?""Type""Name"'Versioning''Group'),
  879.                         );
  880.                     foreach ($deps as $type => $subd{
  881.                         $req ($type == 'required''Yes' 'No';
  882.                         if ($type == 'group'{
  883.                             $group $subd['attribs']['name'];
  884.                         else {
  885.                             $group '';
  886.                         }
  887.  
  888.                         if (!isset($subd[0])) {
  889.                             $subd = array($subd);
  890.                         }
  891.  
  892.                         foreach ($subd as $groupa{
  893.                             foreach ($groupa as $deptype => $depinfo{
  894.                                 if ($deptype == 'attribs'{
  895.                                     continue;
  896.                                 }
  897.  
  898.                                 if ($deptype == 'pearinstaller'{
  899.                                     $deptype 'pear Installer';
  900.                                 }
  901.  
  902.                                 if (!isset($depinfo[0])) {
  903.                                     $depinfo = array($depinfo);
  904.                                 }
  905.  
  906.                                 foreach ($depinfo as $inf{
  907.                                     $name '';
  908.                                     if (isset($inf['channel'])) {
  909.                                         $alias $reg->channelAlias($inf['channel']);
  910.                                         if (!$alias{
  911.                                             $alias '(channel?) ' .$inf['channel'];
  912.                                         }
  913.                                         $name $alias '/';
  914.  
  915.                                     }
  916.                                     if (isset($inf['name'])) {
  917.                                         $name .= $inf['name'];
  918.                                     elseif (isset($inf['pattern'])) {
  919.                                         $name .= $inf['pattern'];
  920.                                     else {
  921.                                         $name .= '';
  922.                                     }
  923.  
  924.                                     if (isset($inf['uri'])) {
  925.                                         $name .= ' [' $inf['uri'.  ']';
  926.                                     }
  927.  
  928.                                     if (isset($inf['conflicts'])) {
  929.                                         $ver 'conflicts';
  930.                                     else {
  931.                                         $ver $d->_getExtraString($inf);
  932.                                     }
  933.  
  934.                                     $data['data'][= array($requcfirst($deptype)$name,
  935.                                         $ver$group);
  936.                                 }
  937.                             }
  938.                         }
  939.                     }
  940.                 }
  941.             }
  942.  
  943.             $this->ui->outputData($data$command);
  944.             return true;
  945.         }
  946.  
  947.         // Fallback
  948.         $this->ui->outputData("This package does not have any dependencies."$command);
  949.     }
  950.  
  951.     function doSign($command$options$params)
  952.     {
  953.         // should move most of this code into PEAR_Packager
  954.         // so it'll be easy to implement "pear package --sign"
  955.         if (count($params!== 1{
  956.             return $this->raiseError("bad parameter(s), try \"help $command\"");
  957.         }
  958.  
  959.         require_once 'System.php';
  960.         require_once 'Archive/Tar.php';
  961.  
  962.         if (!file_exists($params[0])) {
  963.             return $this->raiseError("file does not exist: $params[0]");
  964.         }
  965.  
  966.         $obj $this->getPackageFile($this->config$this->_debug);
  967.         $info $obj->fromTgzFile($params[0]PEAR_VALIDATE_NORMAL);
  968.         if (PEAR::isError($info)) {
  969.             return $this->raiseError($info);
  970.         }
  971.  
  972.         $tar = new Archive_Tar($params[0]);
  973.  
  974.         $tmpdir $this->config->get('temp_dir');
  975.         $tmpdir System::mktemp(' -t "' $tmpdir '" -d pearsign');
  976.         if (!$tar->extractList('package2.xml package.xml package.sig'$tmpdir)) {
  977.             return $this->raiseError("failed to extract tar file");
  978.         }
  979.  
  980.         if (file_exists("$tmpdir/package.sig")) {
  981.             return $this->raiseError("package already signed");
  982.         }
  983.  
  984.         $packagexml 'package.xml';
  985.         if (file_exists("$tmpdir/package2.xml")) {
  986.             $packagexml 'package2.xml';
  987.         }
  988.  
  989.         if (file_exists("$tmpdir/package.sig")) {
  990.             unlink("$tmpdir/package.sig");
  991.         }
  992.  
  993.         if (!file_exists("$tmpdir/$packagexml")) {
  994.             return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
  995.         }
  996.  
  997.         $input $this->ui->userDialog($command,
  998.                                        array('GnuPG Passphrase'),
  999.                                        array('password'));
  1000.         if (!isset($input[0])) {
  1001.             //use empty passphrase
  1002.             $input[0'';
  1003.         }
  1004.  
  1005.         $devnull (isset($options['verbose'])) '' ' 2>/dev/null';
  1006.         $gpg popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull"w");
  1007.         if (!$gpg{
  1008.             return $this->raiseError("gpg command failed");
  1009.         }
  1010.  
  1011.         fwrite($gpg"$input[0]\n");
  1012.         if (pclose($gpg|| !file_exists("$tmpdir/package.sig")) {
  1013.             return $this->raiseError("gpg sign failed");
  1014.         }
  1015.  
  1016.         if (!$tar->addModify("$tmpdir/package.sig"''$tmpdir)) {
  1017.             return $this->raiseError('failed adding signature to file');
  1018.         }
  1019.  
  1020.         $this->ui->outputData("Package signed."$command);
  1021.         return true;
  1022.     }
  1023.  
  1024.     /**
  1025.      * For unit testing purposes
  1026.      */
  1027.     function &getInstaller(&$ui)
  1028.     {
  1029.         if (!class_exists('PEAR_Installer')) {
  1030.             require_once 'PEAR/Installer.php';
  1031.         }
  1032.         $a &new PEAR_Installer($ui);
  1033.         return $a;
  1034.     }
  1035.  
  1036.     /**
  1037.      * For unit testing purposes
  1038.      */
  1039.     function &getCommandPackaging(&$ui&$config)
  1040.     {
  1041.         if (!class_exists('PEAR_Command_Packaging')) {
  1042.             if ($fp @fopen('PEAR/Command/Packaging.php''r'true)) {
  1043.                 fclose($fp);
  1044.                 include_once 'PEAR/Command/Packaging.php';
  1045.             }
  1046.         }
  1047.  
  1048.         if (class_exists('PEAR_Command_Packaging')) {
  1049.             $a &new PEAR_Command_Packaging($ui$config);
  1050.         else {
  1051.             $a = null;
  1052.         }
  1053.  
  1054.         return $a;
  1055.     }
  1056.  
  1057.     function doMakeRPM($command$options$params)
  1058.     {
  1059.  
  1060.         // Check to see if PEAR_Command_Packaging is installed, and
  1061.         // transparently switch to use the "make-rpm-spec" command from it
  1062.         // instead, if it does. Otherwise, continue to use the old version
  1063.         // of "makerpm" supplied with this package (PEAR).
  1064.         $packaging_cmd $this->getCommandPackaging($this->ui$this->config);
  1065.         if ($packaging_cmd !== null{
  1066.             $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
  1067.                 'newer "make-rpm-spec" command instead');
  1068.             return $packaging_cmd->run('make-rpm-spec'$options$params);
  1069.         }
  1070.  
  1071.         $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
  1072.           'improved version is available via "pear make-rpm-spec", which '.
  1073.           'is available by installing PEAR_Command_Packaging');
  1074.         return true;
  1075.     }
  1076.  
  1077.     function doConvert($command$options$params)
  1078.     {
  1079.         $packagexml    = isset($params[0]$params[0'package.xml';
  1080.         $newpackagexml = isset($params[1]$params[1dirname($packagexml.
  1081.             DIRECTORY_SEPARATOR . 'package2.xml';
  1082.         $pkg &$this->getPackageFile($this->config$this->_debug);
  1083.         $pf $pkg->fromPackageFile($packagexmlPEAR_VALIDATE_NORMAL);
  1084.         PEAR::staticPopErrorHandling();
  1085.         if (PEAR::isError($pf)) {
  1086.             if (is_array($pf->getUserInfo())) {
  1087.                 foreach ($pf->getUserInfo(as $warning{
  1088.                     $this->ui->outputData($warning['message']);
  1089.                 }
  1090.             }
  1091.             return $this->raiseError($pf);
  1092.         }
  1093.  
  1094.         if (is_a($pf'PEAR_PackageFile_v2')) {
  1095.             $this->ui->outputData($packagexml ' is already a package.xml version 2.0');
  1096.             return true;
  1097.         }
  1098.  
  1099.         $gen   &$pf->getDefaultGenerator();
  1100.         $newpf &$gen->toV2();
  1101.         $newpf->setPackagefile($newpackagexml);
  1102.         $gen &$newpf->getDefaultGenerator();
  1103.         $state (isset($options['flat']PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
  1104.         $saved $gen->toPackageFile(dirname($newpackagexml)$statebasename($newpackagexml));
  1105.         PEAR::staticPopErrorHandling();
  1106.         if (PEAR::isError($saved)) {
  1107.             if (is_array($saved->getUserInfo())) {
  1108.                 foreach ($saved->getUserInfo(as $warning{
  1109.                     $this->ui->outputData($warning['message']);
  1110.                 }
  1111.             }
  1112.  
  1113.             $this->ui->outputData($saved->getMessage());
  1114.             return true;
  1115.         }
  1116.  
  1117.         $this->ui->outputData('Wrote new version 2.0 package.xml to "' $saved '"');
  1118.         return true;
  1119.     }
  1120. }

Documentation generated on Wed, 06 Jul 2011 23:30:58 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.