Pickle.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <?php
  2. /**
  3. * PEAR_Command_Pickle (pickle command)
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * @category pear
  8. * @package PEAR
  9. * @author Greg Beaver <cellog@php.net>
  10. * @copyright 2005-2009 The Authors
  11. * @license http://opensource.org/licenses/bsd-license.php New BSD License
  12. * @version CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
  13. * @link http://pear.php.net/package/PEAR
  14. * @since File available since Release 1.4.1
  15. */
  16. /**
  17. * base class
  18. */
  19. require_once 'PEAR/Command/Common.php';
  20. /**
  21. * PEAR commands for login/logout
  22. *
  23. * @category pear
  24. * @package PEAR
  25. * @author Greg Beaver <cellog@php.net>
  26. * @copyright 2005-2009 The Authors
  27. * @license http://opensource.org/licenses/bsd-license.php New BSD License
  28. * @version Release: 1.9.4
  29. * @link http://pear.php.net/package/PEAR
  30. * @since Class available since Release 1.4.1
  31. */
  32. class PEAR_Command_Pickle extends PEAR_Command_Common
  33. {
  34. var $commands = array(
  35. 'pickle' => array(
  36. 'summary' => 'Build PECL Package',
  37. 'function' => 'doPackage',
  38. 'shortcut' => 'pi',
  39. 'options' => array(
  40. 'nocompress' => array(
  41. 'shortopt' => 'Z',
  42. 'doc' => 'Do not gzip the package file'
  43. ),
  44. 'showname' => array(
  45. 'shortopt' => 'n',
  46. 'doc' => 'Print the name of the packaged file.',
  47. ),
  48. ),
  49. 'doc' => '[descfile]
  50. Creates a PECL package from its package2.xml file.
  51. An automatic conversion will be made to a package.xml 1.0 and written out to
  52. disk in the current directory as "package.xml". Note that
  53. only simple package.xml 2.0 will be converted. package.xml 2.0 with:
  54. - dependency types other than required/optional PECL package/ext/php/pearinstaller
  55. - more than one extsrcrelease or zendextsrcrelease
  56. - zendextbinrelease, extbinrelease, phprelease, or bundle release type
  57. - dependency groups
  58. - ignore tags in release filelist
  59. - tasks other than replace
  60. - custom roles
  61. will cause pickle to fail, and output an error message. If your package2.xml
  62. uses any of these features, you are best off using PEAR_PackageFileManager to
  63. generate both package.xml.
  64. '
  65. ),
  66. );
  67. /**
  68. * PEAR_Command_Package constructor.
  69. *
  70. * @access public
  71. */
  72. function PEAR_Command_Pickle(&$ui, &$config)
  73. {
  74. parent::PEAR_Command_Common($ui, $config);
  75. }
  76. /**
  77. * For unit-testing ease
  78. *
  79. * @return PEAR_Packager
  80. */
  81. function &getPackager()
  82. {
  83. if (!class_exists('PEAR_Packager')) {
  84. require_once 'PEAR/Packager.php';
  85. }
  86. $a = &new PEAR_Packager;
  87. return $a;
  88. }
  89. /**
  90. * For unit-testing ease
  91. *
  92. * @param PEAR_Config $config
  93. * @param bool $debug
  94. * @param string|null $tmpdir
  95. * @return PEAR_PackageFile
  96. */
  97. function &getPackageFile($config, $debug = false)
  98. {
  99. if (!class_exists('PEAR_Common')) {
  100. require_once 'PEAR/Common.php';
  101. }
  102. if (!class_exists('PEAR_PackageFile')) {
  103. require_once 'PEAR/PackageFile.php';
  104. }
  105. $a = &new PEAR_PackageFile($config, $debug);
  106. $common = new PEAR_Common;
  107. $common->ui = $this->ui;
  108. $a->setLogger($common);
  109. return $a;
  110. }
  111. function doPackage($command, $options, $params)
  112. {
  113. $this->output = '';
  114. $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
  115. $packager = &$this->getPackager();
  116. if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
  117. return $err;
  118. }
  119. $compress = empty($options['nocompress']) ? true : false;
  120. $result = $packager->package($pkginfofile, $compress, 'package.xml');
  121. if (PEAR::isError($result)) {
  122. return $this->raiseError($result);
  123. }
  124. // Don't want output, only the package file name just created
  125. if (isset($options['showname'])) {
  126. $this->ui->outputData($result, $command);
  127. }
  128. return true;
  129. }
  130. function _convertPackage($packagexml)
  131. {
  132. $pkg = &$this->getPackageFile($this->config);
  133. $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
  134. if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
  135. return $this->raiseError('Cannot process "' .
  136. $packagexml . '", is not a package.xml 2.0');
  137. }
  138. require_once 'PEAR/PackageFile/v1.php';
  139. $pf = new PEAR_PackageFile_v1;
  140. $pf->setConfig($this->config);
  141. if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
  142. return $this->raiseError('Cannot safely convert "' . $packagexml .
  143. '", is not an extension source package. Using a PEAR_PackageFileManager-based ' .
  144. 'script is an option');
  145. }
  146. if (is_array($pf2->getUsesRole())) {
  147. return $this->raiseError('Cannot safely convert "' . $packagexml .
  148. '", contains custom roles. Using a PEAR_PackageFileManager-based script or ' .
  149. 'the convert command is an option');
  150. }
  151. if (is_array($pf2->getUsesTask())) {
  152. return $this->raiseError('Cannot safely convert "' . $packagexml .
  153. '", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' .
  154. 'the convert command is an option');
  155. }
  156. $deps = $pf2->getDependencies();
  157. if (isset($deps['group'])) {
  158. return $this->raiseError('Cannot safely convert "' . $packagexml .
  159. '", contains dependency groups. Using a PEAR_PackageFileManager-based script ' .
  160. 'or the convert command is an option');
  161. }
  162. if (isset($deps['required']['subpackage']) ||
  163. isset($deps['optional']['subpackage'])) {
  164. return $this->raiseError('Cannot safely convert "' . $packagexml .
  165. '", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '.
  166. 'script is an option');
  167. }
  168. if (isset($deps['required']['os'])) {
  169. return $this->raiseError('Cannot safely convert "' . $packagexml .
  170. '", contains os dependencies. Using a PEAR_PackageFileManager-based '.
  171. 'script is an option');
  172. }
  173. if (isset($deps['required']['arch'])) {
  174. return $this->raiseError('Cannot safely convert "' . $packagexml .
  175. '", contains arch dependencies. Using a PEAR_PackageFileManager-based '.
  176. 'script is an option');
  177. }
  178. $pf->setPackage($pf2->getPackage());
  179. $pf->setSummary($pf2->getSummary());
  180. $pf->setDescription($pf2->getDescription());
  181. foreach ($pf2->getMaintainers() as $maintainer) {
  182. $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
  183. $maintainer['name'], $maintainer['email']);
  184. }
  185. $pf->setVersion($pf2->getVersion());
  186. $pf->setDate($pf2->getDate());
  187. $pf->setLicense($pf2->getLicense());
  188. $pf->setState($pf2->getState());
  189. $pf->setNotes($pf2->getNotes());
  190. $pf->addPhpDep($deps['required']['php']['min'], 'ge');
  191. if (isset($deps['required']['php']['max'])) {
  192. $pf->addPhpDep($deps['required']['php']['max'], 'le');
  193. }
  194. if (isset($deps['required']['package'])) {
  195. if (!isset($deps['required']['package'][0])) {
  196. $deps['required']['package'] = array($deps['required']['package']);
  197. }
  198. foreach ($deps['required']['package'] as $dep) {
  199. if (!isset($dep['channel'])) {
  200. return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
  201. ' contains uri-based dependency on a package. Using a ' .
  202. 'PEAR_PackageFileManager-based script is an option');
  203. }
  204. if ($dep['channel'] != 'pear.php.net'
  205. && $dep['channel'] != 'pecl.php.net'
  206. && $dep['channel'] != 'doc.php.net') {
  207. return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
  208. ' contains dependency on a non-standard channel package. Using a ' .
  209. 'PEAR_PackageFileManager-based script is an option');
  210. }
  211. if (isset($dep['conflicts'])) {
  212. return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
  213. ' contains conflicts dependency. Using a ' .
  214. 'PEAR_PackageFileManager-based script is an option');
  215. }
  216. if (isset($dep['exclude'])) {
  217. $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
  218. }
  219. if (isset($dep['min'])) {
  220. $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
  221. }
  222. if (isset($dep['max'])) {
  223. $pf->addPackageDep($dep['name'], $dep['max'], 'le');
  224. }
  225. }
  226. }
  227. if (isset($deps['required']['extension'])) {
  228. if (!isset($deps['required']['extension'][0])) {
  229. $deps['required']['extension'] = array($deps['required']['extension']);
  230. }
  231. foreach ($deps['required']['extension'] as $dep) {
  232. if (isset($dep['conflicts'])) {
  233. return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
  234. ' contains conflicts dependency. Using a ' .
  235. 'PEAR_PackageFileManager-based script is an option');
  236. }
  237. if (isset($dep['exclude'])) {
  238. $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
  239. }
  240. if (isset($dep['min'])) {
  241. $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
  242. }
  243. if (isset($dep['max'])) {
  244. $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
  245. }
  246. }
  247. }
  248. if (isset($deps['optional']['package'])) {
  249. if (!isset($deps['optional']['package'][0])) {
  250. $deps['optional']['package'] = array($deps['optional']['package']);
  251. }
  252. foreach ($deps['optional']['package'] as $dep) {
  253. if (!isset($dep['channel'])) {
  254. return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
  255. ' contains uri-based dependency on a package. Using a ' .
  256. 'PEAR_PackageFileManager-based script is an option');
  257. }
  258. if ($dep['channel'] != 'pear.php.net'
  259. && $dep['channel'] != 'pecl.php.net'
  260. && $dep['channel'] != 'doc.php.net') {
  261. return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
  262. ' contains dependency on a non-standard channel package. Using a ' .
  263. 'PEAR_PackageFileManager-based script is an option');
  264. }
  265. if (isset($dep['exclude'])) {
  266. $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
  267. }
  268. if (isset($dep['min'])) {
  269. $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
  270. }
  271. if (isset($dep['max'])) {
  272. $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
  273. }
  274. }
  275. }
  276. if (isset($deps['optional']['extension'])) {
  277. if (!isset($deps['optional']['extension'][0])) {
  278. $deps['optional']['extension'] = array($deps['optional']['extension']);
  279. }
  280. foreach ($deps['optional']['extension'] as $dep) {
  281. if (isset($dep['exclude'])) {
  282. $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
  283. }
  284. if (isset($dep['min'])) {
  285. $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
  286. }
  287. if (isset($dep['max'])) {
  288. $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
  289. }
  290. }
  291. }
  292. $contents = $pf2->getContents();
  293. $release = $pf2->getReleases();
  294. if (isset($releases[0])) {
  295. return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
  296. . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' .
  297. 'or the convert command is an option');
  298. }
  299. if ($configoptions = $pf2->getConfigureOptions()) {
  300. foreach ($configoptions as $option) {
  301. $default = isset($option['default']) ? $option['default'] : false;
  302. $pf->addConfigureOption($option['name'], $option['prompt'], $default);
  303. }
  304. }
  305. if (isset($release['filelist']['ignore'])) {
  306. return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
  307. . 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' .
  308. ' command is an option');
  309. }
  310. if (isset($release['filelist']['install']) &&
  311. !isset($release['filelist']['install'][0])) {
  312. $release['filelist']['install'] = array($release['filelist']['install']);
  313. }
  314. if (isset($contents['dir']['attribs']['baseinstalldir'])) {
  315. $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
  316. } else {
  317. $baseinstalldir = false;
  318. }
  319. if (!isset($contents['dir']['file'][0])) {
  320. $contents['dir']['file'] = array($contents['dir']['file']);
  321. }
  322. foreach ($contents['dir']['file'] as $file) {
  323. if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
  324. $file['attribs']['baseinstalldir'] = $baseinstalldir;
  325. }
  326. $processFile = $file;
  327. unset($processFile['attribs']);
  328. if (count($processFile)) {
  329. foreach ($processFile as $name => $task) {
  330. if ($name != $pf2->getTasksNs() . ':replace') {
  331. return $this->raiseError('Cannot safely process "' . $packagexml .
  332. '" contains tasks other than replace. Using a ' .
  333. 'PEAR_PackageFileManager-based script is an option.');
  334. }
  335. $file['attribs']['replace'][] = $task;
  336. }
  337. }
  338. if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
  339. return $this->raiseError('Cannot safely convert "' . $packagexml .
  340. '", contains custom roles. Using a PEAR_PackageFileManager-based script ' .
  341. 'or the convert command is an option');
  342. }
  343. if (isset($release['filelist']['install'])) {
  344. foreach ($release['filelist']['install'] as $installas) {
  345. if ($installas['attribs']['name'] == $file['attribs']['name']) {
  346. $file['attribs']['install-as'] = $installas['attribs']['as'];
  347. }
  348. }
  349. }
  350. $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
  351. }
  352. if ($pf2->getChangeLog()) {
  353. $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
  354. '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
  355. 'translation for package.xml 1.0');
  356. }
  357. $gen = &$pf->getDefaultGenerator();
  358. $gen->toPackageFile('.');
  359. }
  360. }