Subversion Repositories Applications.gtt

Rev

Rev 94 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
94 jpm 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
 * LICENSE: This source file is subject to version 3.0 of the PHP license
9
 * that is available through the world-wide-web at the following URI:
10
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
11
 * the PHP License and are unable to obtain it through the web, please
12
 * send a note to license@php.net so we can mail you a copy immediately.
13
 *
14
 * @category   pear
15
 * @package    PEAR
16
 * @author     Stig Bakken <ssb@php.net>
17
 * @author     Martin Jansen <mj@php.net>
18
 * @author     Greg Beaver <cellog@php.net>
19
 * @copyright  1997-2006 The PHP Group
20
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
21
 * @version    CVS: $Id: Package.php,v 1.122 2006/06/07 23:38:14 pajoye Exp $
22
 * @link       http://pear.php.net/package/PEAR
23
 * @since      File available since Release 0.1
24
 */
25
 
26
/**
27
 * base class
28
 */
29
require_once 'PEAR/Command/Common.php';
30
 
31
/**
32
 * PEAR commands for login/logout
33
 *
34
 * @category   pear
35
 * @package    PEAR
36
 * @author     Stig Bakken <ssb@php.net>
37
 * @author     Martin Jansen <mj@php.net>
38
 * @author     Greg Beaver <cellog@php.net>
39
 * @copyright  1997-2006 The PHP Group
40
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
41
 * @version    Release: 1.5.1
42
 * @link       http://pear.php.net/package/PEAR
43
 * @since      Class available since Release 0.1
44
 */
45
 
46
class PEAR_Command_Package extends PEAR_Command_Common
47
{
48
    // {{{ properties
49
 
50
    var $commands = array(
51
        'package' => array(
52
            'summary' => 'Build Package',
53
            'function' => 'doPackage',
54
            'shortcut' => 'p',
55
            'options' => array(
56
                'nocompress' => array(
57
                    'shortopt' => 'Z',
58
                    'doc' => 'Do not gzip the package file'
59
                    ),
60
                'showname' => array(
61
                    'shortopt' => 'n',
62
                    'doc' => 'Print the name of the packaged file.',
63
                    ),
64
                ),
65
            'doc' => '[descfile] [descfile2]
66
Creates a PEAR package from its description file (usually called
67
package.xml).  If a second packagefile is passed in, then
68
the packager will check to make sure that one is a package.xml
69
version 1.0, and the other is a package.xml version 2.0.  The
70
package.xml version 1.0 will be saved as "package.xml" in the archive,
71
and the other as "package2.xml" in the archive"
72
'
73
            ),
74
        'package-validate' => array(
75
            'summary' => 'Validate Package Consistency',
76
            'function' => 'doPackageValidate',
77
            'shortcut' => 'pv',
78
            'options' => array(),
79
            'doc' => '
80
',
81
            ),
82
        'cvsdiff' => array(
83
            'summary' => 'Run a "cvs diff" for all files in a package',
84
            'function' => 'doCvsDiff',
85
            'shortcut' => 'cd',
86
            'options' => array(
87
                'quiet' => array(
88
                    'shortopt' => 'q',
89
                    'doc' => 'Be quiet',
90
                    ),
91
                'reallyquiet' => array(
92
                    'shortopt' => 'Q',
93
                    'doc' => 'Be really quiet',
94
                    ),
95
                'date' => array(
96
                    'shortopt' => 'D',
97
                    'doc' => 'Diff against revision of DATE',
98
                    'arg' => 'DATE',
99
                    ),
100
                'release' => array(
101
                    'shortopt' => 'R',
102
                    'doc' => 'Diff against tag for package release REL',
103
                    'arg' => 'REL',
104
                    ),
105
                'revision' => array(
106
                    'shortopt' => 'r',
107
                    'doc' => 'Diff against revision REV',
108
                    'arg' => 'REV',
109
                    ),
110
                'context' => array(
111
                    'shortopt' => 'c',
112
                    'doc' => 'Generate context diff',
113
                    ),
114
                'unified' => array(
115
                    'shortopt' => 'u',
116
                    'doc' => 'Generate unified diff',
117
                    ),
118
                'ignore-case' => array(
119
                    'shortopt' => 'i',
120
                    'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
121
                    ),
122
                'ignore-whitespace' => array(
123
                    'shortopt' => 'b',
124
                    'doc' => 'Ignore changes in amount of white space',
125
                    ),
126
                'ignore-blank-lines' => array(
127
                    'shortopt' => 'B',
128
                    'doc' => 'Ignore changes that insert or delete blank lines',
129
                    ),
130
                'brief' => array(
131
                    'doc' => 'Report only whether the files differ, no details',
132
                    ),
133
                'dry-run' => array(
134
                    'shortopt' => 'n',
135
                    'doc' => 'Don\'t do anything, just pretend',
136
                    ),
137
                ),
138
            'doc' => '<package.xml>
139
Compares all the files in a package.  Without any options, this
140
command will compare the current code with the last checked-in code.
141
Using the -r or -R option you may compare the current code with that
142
of a specific release.
143
',
144
            ),
145
        'cvstag' => array(
146
            'summary' => 'Set CVS Release Tag',
147
            'function' => 'doCvsTag',
148
            'shortcut' => 'ct',
149
            'options' => array(
150
                'quiet' => array(
151
                    'shortopt' => 'q',
152
                    'doc' => 'Be quiet',
153
                    ),
154
                'reallyquiet' => array(
155
                    'shortopt' => 'Q',
156
                    'doc' => 'Be really quiet',
157
                    ),
158
                'slide' => array(
159
                    'shortopt' => 'F',
160
                    'doc' => 'Move (slide) tag if it exists',
161
                    ),
162
                'delete' => array(
163
                    'shortopt' => 'd',
164
                    'doc' => 'Remove tag',
165
                    ),
166
                'dry-run' => array(
167
                    'shortopt' => 'n',
168
                    'doc' => 'Don\'t do anything, just pretend',
169
                    ),
170
                ),
171
            'doc' => '<package.xml> [files...]
172
Sets a CVS tag on all files in a package.  Use this command after you have
173
packaged a distribution tarball with the "package" command to tag what
174
revisions of what files were in that release.  If need to fix something
175
after running cvstag once, but before the tarball is released to the public,
176
use the "slide" option to move the release tag.
177
 
178
to include files (such as a second package.xml, or tests not included in the
179
release), pass them as additional parameters.
180
',
181
            ),
182
        'package-dependencies' => array(
183
            'summary' => 'Show package dependencies',
184
            'function' => 'doPackageDependencies',
185
            'shortcut' => 'pd',
186
            'options' => array(),
187
            'doc' => '
188
List all dependencies the package has.'
189
            ),
190
        'sign' => array(
191
            'summary' => 'Sign a package distribution file',
192
            'function' => 'doSign',
193
            'shortcut' => 'si',
194
            'options' => array(),
195
            'doc' => '<package-file>
196
Signs a package distribution (.tar or .tgz) file with GnuPG.',
197
            ),
198
        'makerpm' => array(
199
            'summary' => 'Builds an RPM spec file from a PEAR package',
200
            'function' => 'doMakeRPM',
201
            'shortcut' => 'rpm',
202
            'options' => array(
203
                'spec-template' => array(
204
                    'shortopt' => 't',
205
                    'arg' => 'FILE',
206
                    'doc' => 'Use FILE as RPM spec file template'
207
                    ),
208
                'rpm-pkgname' => array(
209
                    'shortopt' => 'p',
210
                    'arg' => 'FORMAT',
211
                    'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
212
by the PEAR package name, defaults to "PEAR::%s".',
213
                    ),
214
                ),
215
            'doc' => '<package-file>
216
 
217
Creates an RPM .spec file for wrapping a PEAR package inside an RPM
218
package.  Intended to be used from the SPECS directory, with the PEAR
219
package tarball in the SOURCES directory:
220
 
221
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
222
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
223
$ rpm -bb PEAR::Net_Socket-1.0.spec
224
...
225
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
226
',
227
            ),
228
        'convert' => array(
229
            'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
230
            'function' => 'doConvert',
231
            'shortcut' => 'c2',
232
            'options' => array(
233
                'flat' => array(
234
                    'shortopt' => 'f',
235
                    'doc' => 'do not beautify the filelist.',
236
                    ),
237
                ),
238
            'doc' => '[descfile] [descfile2]
239
Converts a package.xml in 1.0 format into a package.xml
240
in 2.0 format.  The new file will be named package2.xml by default,
241
and package.xml will be used as the old file by default.
242
This is not the most intelligent conversion, and should only be
243
used for automated conversion or learning the format.
244
'
245
            ),
246
        );
247
 
248
    var $output;
249
 
250
    // }}}
251
    // {{{ constructor
252
 
253
    /**
254
     * PEAR_Command_Package constructor.
255
     *
256
     * @access public
257
     */
258
    function PEAR_Command_Package(&$ui, &$config)
259
    {
260
        parent::PEAR_Command_Common($ui, $config);
261
    }
262
 
263
    // }}}
264
 
265
    // {{{ _displayValidationResults()
266
 
267
    function _displayValidationResults($err, $warn, $strict = false)
268
    {
269
        foreach ($err as $e) {
270
            $this->output .= "Error: $e\n";
271
        }
272
        foreach ($warn as $w) {
273
            $this->output .= "Warning: $w\n";
274
        }
275
        $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
276
                                       sizeof($err), sizeof($warn));
277
        if ($strict && sizeof($err) > 0) {
278
            $this->output .= "Fix these errors and try again.";
279
            return false;
280
        }
281
        return true;
282
    }
283
 
284
    // }}}
285
    function &getPackager()
286
    {
287
        if (!class_exists('PEAR_Packager')) {
288
            require_once 'PEAR/Packager.php';
289
        }
290
        $a = &new PEAR_Packager;
291
        return $a;
292
    }
293
 
294
    function &getPackageFile($config, $debug = false, $tmpdir = null)
295
    {
296
        if (!class_exists('PEAR_Common')) {
297
            require_once 'PEAR/Common.php';
298
        }
299
        if (!class_exists('PEAR/PackageFile.php')) {
300
            require_once 'PEAR/PackageFile.php';
301
        }
302
        $a = &new PEAR_PackageFile($config, $debug, $tmpdir);
303
        $common = new PEAR_Common;
304
        $common->ui = $this->ui;
305
        $a->setLogger($common);
306
        return $a;
307
    }
308
    // {{{ doPackage()
309
 
310
    function doPackage($command, $options, $params)
311
    {
312
        $this->output = '';
313
        $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
314
        $pkg2 = isset($params[1]) ? $params[1] : null;
315
        if (!$pkg2 && !isset($params[0])) {
316
            if (file_exists('package2.xml')) {
317
                $pkg2 = 'package2.xml';
318
            }
319
        }
320
        $packager = &$this->getPackager();
321
        $compress = empty($options['nocompress']) ? true : false;
322
        $result = $packager->package($pkginfofile, $compress, $pkg2);
323
        if (PEAR::isError($result)) {
324
            return $this->raiseError($result);
325
        }
326
        // Don't want output, only the package file name just created
327
        if (isset($options['showname'])) {
328
            $this->output = $result;
329
        }
330
        if ($this->output) {
331
            $this->ui->outputData($this->output, $command);
332
        }
333
        return true;
334
    }
335
 
336
    // }}}
337
    // {{{ doPackageValidate()
338
 
339
    function doPackageValidate($command, $options, $params)
340
    {
341
        $this->output = '';
342
        if (sizeof($params) < 1) {
343
            $params[0] = "package.xml";
344
        }
345
        $obj = &$this->getPackageFile($this->config, $this->_debug);
346
        $obj->rawReturn();
347
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
348
        $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
349
        if (PEAR::isError($info)) {
350
            $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
351
        } else {
352
            $archive = $info->getArchiveFile();
353
            $tar = &new Archive_Tar($archive);
354
            $tar->extract(dirname($info->getPackageFile()));
355
            $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
356
                $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
357
                basename($info->getPackageFile()));
358
        }
359
        PEAR::staticPopErrorHandling();
360
        if (PEAR::isError($info)) {
361
            return $this->raiseError($info);
362
        }
363
        $valid = false;
364
        if ($info->getPackagexmlVersion() == '2.0') {
365
            if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
366
                $info->flattenFileList();
367
                $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
368
            }
369
        } else {
370
            $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
371
        }
372
        $err = array();
373
        $warn = array();
374
        if (!$valid) {
375
            foreach ($info->getValidationWarnings() as $error) {
376
                if ($error['level'] == 'warning') {
377
                    $warn[] = $error['message'];
378
                } else {
379
                    $err[] = $error['message'];
380
                }
381
            }
382
        }
383
        $this->_displayValidationResults($err, $warn);
384
        $this->ui->outputData($this->output, $command);
385
        return true;
386
    }
387
 
388
    // }}}
389
    // {{{ doCvsTag()
390
 
391
    function doCvsTag($command, $options, $params)
392
    {
393
        $this->output = '';
394
        $_cmd = $command;
395
        if (sizeof($params) < 1) {
396
            $help = $this->getHelp($command);
397
            return $this->raiseError("$command: missing parameter: $help[0]");
398
        }
399
        $obj = &$this->getPackageFile($this->config, $this->_debug);
400
        $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
401
        if (PEAR::isError($info)) {
402
            return $this->raiseError($info);
403
        }
404
        $err = $warn = array();
405
        if (!$info->validate()) {
406
            foreach ($info->getValidationWarnings() as $error) {
407
                if ($error['level'] == 'warning') {
408
                    $warn[] = $error['message'];
409
                } else {
410
                    $err[] = $error['message'];
411
                }
412
            }
413
        }
414
        if (!$this->_displayValidationResults($err, $warn, true)) {
415
            $this->ui->outputData($this->output, $command);
416
            return $this->raiseError('CVS tag failed');
417
        }
418
        $version = $info->getVersion();
419
        $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
420
        $cvstag = "RELEASE_$cvsversion";
421
        $files = array_keys($info->getFilelist());
422
        $command = "cvs";
423
        if (isset($options['quiet'])) {
424
            $command .= ' -q';
425
        }
426
        if (isset($options['reallyquiet'])) {
427
            $command .= ' -Q';
428
        }
429
        $command .= ' tag';
430
        if (isset($options['slide'])) {
431
            $command .= ' -F';
432
        }
433
        if (isset($options['delete'])) {
434
            $command .= ' -d';
435
        }
436
        $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
437
        array_shift($params);
438
        if (count($params)) {
439
            // add in additional files to be tagged
440
            $files = array_merge($files, $params);
441
        }
442
        foreach ($files as $file) {
443
            $command .= ' ' . escapeshellarg($file);
444
        }
445
        if ($this->config->get('verbose') > 1) {
446
            $this->output .= "+ $command\n";
447
        }
448
        $this->output .= "+ $command\n";
449
        if (empty($options['dry-run'])) {
450
            $fp = popen($command, "r");
451
            while ($line = fgets($fp, 1024)) {
452
                $this->output .= rtrim($line)."\n";
453
            }
454
            pclose($fp);
455
        }
456
        $this->ui->outputData($this->output, $_cmd);
457
        return true;
458
    }
459
 
460
    // }}}
461
    // {{{ doCvsDiff()
462
 
463
    function doCvsDiff($command, $options, $params)
464
    {
465
        $this->output = '';
466
        if (sizeof($params) < 1) {
467
            $help = $this->getHelp($command);
468
            return $this->raiseError("$command: missing parameter: $help[0]");
469
        }
470
        $obj = &$this->getPackageFile($this->config, $this->_debug);
471
        $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
472
        if (PEAR::isError($info)) {
473
            return $this->raiseError($info);
474
        }
475
        $err = $warn = array();
476
        if (!$info->validate()) {
477
            foreach ($info->getValidationWarnings() as $error) {
478
                if ($error['level'] == 'warning') {
479
                    $warn[] = $error['message'];
480
                } else {
481
                    $err[] = $error['message'];
482
                }
483
            }
484
        }
485
        if (!$this->_displayValidationResults($err, $warn, true)) {
486
            $this->ui->outputData($this->output, $command);
487
            return $this->raiseError('CVS diff failed');
488
        }
489
        $info1 = $info->getFilelist();
490
        $files = $info1;
491
        $cmd = "cvs";
492
        if (isset($options['quiet'])) {
493
            $cmd .= ' -q';
494
            unset($options['quiet']);
495
        }
496
        if (isset($options['reallyquiet'])) {
497
            $cmd .= ' -Q';
498
            unset($options['reallyquiet']);
499
        }
500
        if (isset($options['release'])) {
501
            $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
502
            $cvstag = "RELEASE_$cvsversion";
503
            $options['revision'] = $cvstag;
504
            unset($options['release']);
505
        }
506
        $execute = true;
507
        if (isset($options['dry-run'])) {
508
            $execute = false;
509
            unset($options['dry-run']);
510
        }
511
        $cmd .= ' diff';
512
        // the rest of the options are passed right on to "cvs diff"
513
        foreach ($options as $option => $optarg) {
514
            $arg = $short = false;
515
            if (isset($this->commands[$command]['options'][$option])) {
516
                $arg = $this->commands[$command]['options'][$option]['arg'];
517
                $short = $this->commands[$command]['options'][$option]['shortopt'];
518
            }
519
            $cmd .= $short ? " -$short" : " --$option";
520
            if ($arg && $optarg) {
521
                $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
522
            }
523
        }
524
        foreach ($files as $file) {
525
            $cmd .= ' ' . escapeshellarg($file['name']);
526
        }
527
        if ($this->config->get('verbose') > 1) {
528
            $this->output .= "+ $cmd\n";
529
        }
530
        if ($execute) {
531
            $fp = popen($cmd, "r");
532
            while ($line = fgets($fp, 1024)) {
533
                $this->output .= rtrim($line)."\n";
534
            }
535
            pclose($fp);
536
        }
537
        $this->ui->outputData($this->output, $command);
538
        return true;
539
    }
540
 
541
    // }}}
542
    // {{{ doPackageDependencies()
543
 
544
    function doPackageDependencies($command, $options, $params)
545
    {
546
        // $params[0] -> the PEAR package to list its information
547
        if (sizeof($params) != 1) {
548
            return $this->raiseError("bad parameter(s), try \"help $command\"");
549
        }
550
        $obj = &$this->getPackageFile($this->config, $this->_debug);
551
        $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
552
        if (PEAR::isError($info)) {
553
            return $this->raiseError($info);
554
        }
555
        $deps = $info->getDeps();
556
        if (is_array($deps)) {
557
            if ($info->getPackagexmlVersion() == '1.0') {
558
                $data = array(
559
                    'caption' => 'Dependencies for pear/' . $info->getPackage(),
560
                    'border' => true,
561
                    'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
562
                    );
563
 
564
                foreach ($deps as $d) {
565
                    if (isset($d['optional'])) {
566
                        if ($d['optional'] == 'yes') {
567
                            $req = 'No';
568
                        } else {
569
                            $req = 'Yes';
570
                        }
571
                    } else {
572
                        $req = 'Yes';
573
                    }
574
                    if (isset($this->_deps_rel_trans[$d['rel']])) {
575
                        $rel = $this->_deps_rel_trans[$d['rel']];
576
                    } else {
577
                        $rel = $d['rel'];
578
                    }
579
 
580
                    if (isset($this->_deps_type_trans[$d['type']])) {
581
                        $type = ucfirst($this->_deps_type_trans[$d['type']]);
582
                    } else {
583
                        $type = $d['type'];
584
                    }
585
 
586
                    if (isset($d['name'])) {
587
                        $name = $d['name'];
588
                    } else {
589
                        $name = '';
590
                    }
591
 
592
                    if (isset($d['version'])) {
593
                        $version = $d['version'];
594
                    } else {
595
                        $version = '';
596
                    }
597
 
598
                    $data['data'][] = array($req, $type, $name, $rel, $version);
599
                }
600
            } else { // package.xml 2.0 dependencies display
601
                require_once 'PEAR/Dependency2.php';
602
                $deps = $info->getDependencies();
603
                $reg = &$this->config->getRegistry();
604
                if (is_array($deps)) {
605
                    $d = new PEAR_Dependency2($this->config, array(), '');
606
                    $data = array(
607
                        'caption' => 'Dependencies for ' . $info->getPackage(),
608
                        'border' => true,
609
                        'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
610
                        );
611
                    foreach ($deps as $type => $subd) {
612
                        $req = ($type == 'required') ? 'Yes' : 'No';
613
                        if ($type == 'group') {
614
                            $group = $subd['attribs']['name'];
615
                        } else {
616
                            $group = '';
617
                        }
618
                        if (!isset($subd[0])) {
619
                            $subd = array($subd);
620
                        }
621
                        foreach ($subd as $groupa) {
622
                            foreach ($groupa as $deptype => $depinfo) {
623
                                if ($deptype == 'attribs') {
624
                                    continue;
625
                                }
626
                                if ($deptype == 'pearinstaller') {
627
                                    $deptype = 'pear Installer';
628
                                }
629
                                if (!isset($depinfo[0])) {
630
                                    $depinfo = array($depinfo);
631
                                }
632
                                foreach ($depinfo as $inf) {
633
                                    $name = '';
634
                                    if (isset($inf['channel'])) {
635
                                        $alias = $reg->channelAlias($inf['channel']);
636
                                        if (!$alias) {
637
                                            $alias = '(channel?) ' .$inf['channel'];
638
                                        }
639
                                        $name = $alias . '/';
640
                                    }
641
                                    if (isset($inf['name'])) {
642
                                        $name .= $inf['name'];
643
                                    } elseif (isset($inf['pattern'])) {
644
                                        $name .= $inf['pattern'];
645
                                    } else {
646
                                        $name .= '';
647
                                    }
648
                                    if (isset($inf['uri'])) {
649
                                        $name .= ' [' . $inf['uri'] .  ']';
650
                                    }
651
                                    if (isset($inf['conflicts'])) {
652
                                        $ver = 'conflicts';
653
                                    } else {
654
                                        $ver = $d->_getExtraString($inf);
655
                                    }
656
                                    $data['data'][] = array($req, ucfirst($deptype), $name,
657
                                        $ver, $group);
658
                                }
659
                            }
660
                        }
661
                    }
662
                }
663
            }
664
 
665
            $this->ui->outputData($data, $command);
666
            return true;
667
        }
668
 
669
        // Fallback
670
        $this->ui->outputData("This package does not have any dependencies.", $command);
671
    }
672
 
673
    // }}}
674
    // {{{ doSign()
675
 
676
    function doSign($command, $options, $params)
677
    {
678
        require_once 'System.php';
679
        require_once 'Archive/Tar.php';
680
        // should move most of this code into PEAR_Packager
681
        // so it'll be easy to implement "pear package --sign"
682
        if (sizeof($params) != 1) {
683
            return $this->raiseError("bad parameter(s), try \"help $command\"");
684
        }
685
        if (!file_exists($params[0])) {
686
            return $this->raiseError("file does not exist: $params[0]");
687
        }
688
        $obj = $this->getPackageFile($this->config, $this->_debug);
689
        $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
690
        if (PEAR::isError($info)) {
691
            return $this->raiseError($info);
692
        }
693
        $tar = new Archive_Tar($params[0]);
694
        $tmpdir = System::mktemp('-d pearsign');
695
        if (!$tar->extractList('package2.xml package.sig', $tmpdir)) {
696
            if (!$tar->extractList('package.xml package.sig', $tmpdir)) {
697
                return $this->raiseError("failed to extract tar file");
698
            }
699
        }
700
        if (file_exists("$tmpdir/package.sig")) {
701
            return $this->raiseError("package already signed");
702
        }
703
        $packagexml = 'package.xml';
704
        if (file_exists("$tmpdir/package2.xml")) {
705
            $packagexml = 'package2.xml';
706
        }
707
        if (file_exists("$tmpdir/package.sig")) {
708
            unlink("$tmpdir/package.sig");
709
        }
710
        $input = $this->ui->userDialog($command,
711
                                       array('GnuPG Passphrase'),
712
                                       array('password'));
713
        $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml 2>/dev/null", "w");
714
        if (!$gpg) {
715
            return $this->raiseError("gpg command failed");
716
        }
717
        fwrite($gpg, "$input[0]\n");
718
        if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
719
            return $this->raiseError("gpg sign failed");
720
        }
721
        $tar->addModify("$tmpdir/package.sig", '', $tmpdir);
722
        return true;
723
    }
724
 
725
    // }}}
726
 
727
    /**
728
     * For unit testing purposes
729
     */
730
    function &getInstaller(&$ui)
731
    {
732
        if (!class_exists('PEAR_Installer')) {
733
            require_once 'PEAR/Installer.php';
734
        }
735
        $a = &new PEAR_Installer($ui);
736
        return $a;
737
    }
738
 
739
    /**
740
     * For unit testing purposes
741
     */
742
    function &getCommandPackaging(&$ui, &$config)
743
    {
744
        if (!class_exists('PEAR_Command_Packaging')) {
745
            if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
746
                fclose($fp);
747
                include_once 'PEAR/Command/Packaging.php';
748
            }
749
        }
750
 
751
        if (class_exists('PEAR_Command_Packaging')) {
752
            $a = &new PEAR_Command_Packaging($ui, $config);
753
        } else {
754
            $a = null;
755
        }
756
        return $a;
757
    }
758
 
759
    // {{{ doMakeRPM()
760
 
761
    function doMakeRPM($command, $options, $params)
762
    {
763
 
764
        // Check to see if PEAR_Command_Packaging is installed, and
765
        // transparently switch to use the "make-rpm-spec" command from it
766
        // instead, if it does. Otherwise, continue to use the old version
767
        // of "makerpm" supplied with this package (PEAR).
768
        $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
769
        if ($packaging_cmd !== null) {
770
            $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
771
                'newer "make-rpm-spec" command instead');
772
            return $packaging_cmd->run('make-rpm-spec', $options, $params);
773
        } else {
774
            $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
775
              'improved version is available via "pear make-rpm-spec", which '.
776
              'is available by installing PEAR_Command_Packaging');
777
        }
778
        return true;
779
    }
780
 
781
    function doConvert($command, $options, $params)
782
    {
783
        $packagexml = isset($params[0]) ? $params[0] : 'package.xml';
784
        $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
785
            DIRECTORY_SEPARATOR . 'package2.xml';
786
        $pkg = &$this->getPackageFile($this->config, $this->_debug);
787
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
788
        $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
789
        PEAR::staticPopErrorHandling();
790
        if (!PEAR::isError($pf)) {
791
            if (is_a($pf, 'PEAR_PackageFile_v2')) {
792
                $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
793
                return true;
794
            }
795
            $gen = &$pf->getDefaultGenerator();
796
            $newpf = &$gen->toV2();
797
            $newpf->setPackagefile($newpackagexml);
798
            $gen = &$newpf->getDefaultGenerator();
799
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
800
            $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
801
            $saved = $gen->toPackageFile(dirname($newpackagexml), $state,
802
                basename($newpackagexml));
803
            PEAR::staticPopErrorHandling();
804
            if (PEAR::isError($saved)) {
805
                if (is_array($saved->getUserInfo())) {
806
                    foreach ($saved->getUserInfo() as $warning) {
807
                        $this->ui->outputData($warning['message']);
808
                    }
809
                }
810
                $this->ui->outputData($saved->getMessage());
811
                return true;
812
            }
813
            $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
814
            return true;
815
        } else {
816
            if (is_array($pf->getUserInfo())) {
817
                foreach ($pf->getUserInfo() as $warning) {
818
                    $this->ui->outputData($warning['message']);
819
                }
820
            }
821
            return $this->raiseError($pf);
822
        }
823
    }
824
 
825
    // }}}
826
}
827
 
828
?>