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_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
4
 *
5
 * PHP versions 4 and 5
6
 *
7
 * @category   pear
8
 * @package    PEAR
9
 * @author     Stig Bakken <ssb@php.net>
10
 * @author     Greg Beaver <cellog@php.net>
187 mathias 11
 * @copyright  1997-2009 The Authors
12
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
94 jpm 13
 * @link       http://pear.php.net/package/PEAR
14
 * @since      File available since Release 0.1
15
 */
16
 
17
/**
18
 * base class
19
 */
20
require_once 'PEAR/Command/Common.php';
21
 
22
/**
23
 * PEAR commands for installation or deinstallation/upgrading of
24
 * packages.
25
 *
26
 * @category   pear
27
 * @package    PEAR
28
 * @author     Stig Bakken <ssb@php.net>
29
 * @author     Greg Beaver <cellog@php.net>
187 mathias 30
 * @copyright  1997-2009 The Authors
31
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
32
 * @version    Release: 1.10.1
94 jpm 33
 * @link       http://pear.php.net/package/PEAR
34
 * @since      Class available since Release 0.1
35
 */
36
class PEAR_Command_Install extends PEAR_Command_Common
37
{
38
    // {{{ properties
39
 
40
    var $commands = array(
41
        'install' => array(
42
            'summary' => 'Install Package',
43
            'function' => 'doInstall',
44
            'shortcut' => 'i',
45
            'options' => array(
46
                'force' => array(
47
                    'shortopt' => 'f',
48
                    'doc' => 'will overwrite newer installed packages',
49
                    ),
50
                'loose' => array(
51
                    'shortopt' => 'l',
52
                    'doc' => 'do not check for recommended dependency version',
53
                    ),
54
                'nodeps' => array(
55
                    'shortopt' => 'n',
56
                    'doc' => 'ignore dependencies, install anyway',
57
                    ),
58
                'register-only' => array(
59
                    'shortopt' => 'r',
60
                    'doc' => 'do not install files, only register the package as installed',
61
                    ),
62
                'soft' => array(
63
                    'shortopt' => 's',
64
                    'doc' => 'soft install, fail silently, or upgrade if already installed',
65
                    ),
66
                'nobuild' => array(
67
                    'shortopt' => 'B',
68
                    'doc' => 'don\'t build C extensions',
69
                    ),
70
                'nocompress' => array(
71
                    'shortopt' => 'Z',
72
                    'doc' => 'request uncompressed files when downloading',
73
                    ),
74
                'installroot' => array(
75
                    'shortopt' => 'R',
76
                    'arg' => 'DIR',
77
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
78
                    ),
79
                'packagingroot' => array(
80
                    'shortopt' => 'P',
81
                    'arg' => 'DIR',
82
                    'doc' => 'root directory used when packaging files, like RPM packaging',
83
                    ),
84
                'ignore-errors' => array(
85
                    'doc' => 'force install even if there were errors',
86
                    ),
87
                'alldeps' => array(
88
                    'shortopt' => 'a',
89
                    'doc' => 'install all required and optional dependencies',
90
                    ),
91
                'onlyreqdeps' => array(
92
                    'shortopt' => 'o',
93
                    'doc' => 'install all required dependencies',
94
                    ),
95
                'offline' => array(
96
                    'shortopt' => 'O',
97
                    'doc' => 'do not attempt to download any urls or contact channels',
98
                    ),
99
                'pretend' => array(
100
                    'shortopt' => 'p',
101
                    'doc' => 'Only list the packages that would be downloaded',
102
                    ),
103
                ),
104
            'doc' => '[channel/]<package> ...
105
Installs one or more PEAR packages.  You can specify a package to
106
install in four ways:
107
 
108
"Package-1.0.tgz" : installs from a local file
109
 
110
"http://example.com/Package-1.0.tgz" : installs from
111
anywhere on the net.
112
 
113
"package.xml" : installs the package described in
114
package.xml.  Useful for testing, or for wrapping a PEAR package in
115
another package manager such as RPM.
116
 
117
"Package[-version/state][.tar]" : queries your default channel\'s server
118
({config master_server}) and downloads the newest package with
119
the preferred quality/state ({config preferred_state}).
120
 
121
To retrieve Package version 1.1, use "Package-1.1," to retrieve
122
Package state beta, use "Package-beta."  To retrieve an uncompressed
123
file, append .tar (make sure there is no file by the same name first)
124
 
125
To download a package from another channel, prefix with the channel name like
126
"channel/Package"
127
 
128
More than one package may be specified at once.  It is ok to mix these
129
four ways of specifying packages.
130
'),
131
        'upgrade' => array(
132
            'summary' => 'Upgrade Package',
133
            'function' => 'doInstall',
134
            'shortcut' => 'up',
135
            'options' => array(
187 mathias 136
                'channel' => array(
137
                    'shortopt' => 'c',
138
                    'doc' => 'upgrade packages from a specific channel',
139
                    'arg' => 'CHAN',
140
                    ),
94 jpm 141
                'force' => array(
142
                    'shortopt' => 'f',
143
                    'doc' => 'overwrite newer installed packages',
144
                    ),
145
                'loose' => array(
146
                    'shortopt' => 'l',
147
                    'doc' => 'do not check for recommended dependency version',
148
                    ),
149
                'nodeps' => array(
150
                    'shortopt' => 'n',
151
                    'doc' => 'ignore dependencies, upgrade anyway',
152
                    ),
153
                'register-only' => array(
154
                    'shortopt' => 'r',
155
                    'doc' => 'do not install files, only register the package as upgraded',
156
                    ),
157
                'nobuild' => array(
158
                    'shortopt' => 'B',
159
                    'doc' => 'don\'t build C extensions',
160
                    ),
161
                'nocompress' => array(
162
                    'shortopt' => 'Z',
163
                    'doc' => 'request uncompressed files when downloading',
164
                    ),
165
                'installroot' => array(
166
                    'shortopt' => 'R',
167
                    'arg' => 'DIR',
187 mathias 168
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
94 jpm 169
                    ),
170
                'ignore-errors' => array(
171
                    'doc' => 'force install even if there were errors',
172
                    ),
173
                'alldeps' => array(
174
                    'shortopt' => 'a',
175
                    'doc' => 'install all required and optional dependencies',
176
                    ),
177
                'onlyreqdeps' => array(
178
                    'shortopt' => 'o',
179
                    'doc' => 'install all required dependencies',
180
                    ),
181
                'offline' => array(
182
                    'shortopt' => 'O',
183
                    'doc' => 'do not attempt to download any urls or contact channels',
184
                    ),
185
                'pretend' => array(
186
                    'shortopt' => 'p',
187
                    'doc' => 'Only list the packages that would be downloaded',
188
                    ),
189
                ),
190
            'doc' => '<package> ...
191
Upgrades one or more PEAR packages.  See documentation for the
192
"install" command for ways to specify a package.
193
 
194
When upgrading, your package will be updated if the provided new
195
package has a higher version number (use the -f option if you need to
196
upgrade anyway).
197
 
198
More than one package may be specified at once.
199
'),
200
        'upgrade-all' => array(
187 mathias 201
            'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
202
            'function' => 'doUpgradeAll',
94 jpm 203
            'shortcut' => 'ua',
204
            'options' => array(
187 mathias 205
                'channel' => array(
206
                    'shortopt' => 'c',
207
                    'doc' => 'upgrade packages from a specific channel',
208
                    'arg' => 'CHAN',
209
                    ),
94 jpm 210
                'nodeps' => array(
211
                    'shortopt' => 'n',
212
                    'doc' => 'ignore dependencies, upgrade anyway',
213
                    ),
214
                'register-only' => array(
215
                    'shortopt' => 'r',
216
                    'doc' => 'do not install files, only register the package as upgraded',
217
                    ),
218
                'nobuild' => array(
219
                    'shortopt' => 'B',
220
                    'doc' => 'don\'t build C extensions',
221
                    ),
222
                'nocompress' => array(
223
                    'shortopt' => 'Z',
224
                    'doc' => 'request uncompressed files when downloading',
225
                    ),
226
                'installroot' => array(
227
                    'shortopt' => 'R',
228
                    'arg' => 'DIR',
229
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
230
                    ),
231
                'ignore-errors' => array(
232
                    'doc' => 'force install even if there were errors',
233
                    ),
234
                'loose' => array(
235
                    'doc' => 'do not check for recommended dependency version',
236
                    ),
237
                ),
238
            'doc' => '
187 mathias 239
WARNING: This function is deprecated in favor of using the upgrade command with no params
240
 
94 jpm 241
Upgrades all packages that have a newer release available.  Upgrades are
242
done only if there is a release available of the state specified in
243
"preferred_state" (currently {config preferred_state}), or a state considered
244
more stable.
245
'),
246
        'uninstall' => array(
247
            'summary' => 'Un-install Package',
248
            'function' => 'doUninstall',
249
            'shortcut' => 'un',
250
            'options' => array(
251
                'nodeps' => array(
252
                    'shortopt' => 'n',
253
                    'doc' => 'ignore dependencies, uninstall anyway',
254
                    ),
255
                'register-only' => array(
256
                    'shortopt' => 'r',
257
                    'doc' => 'do not remove files, only register the packages as not installed',
258
                    ),
259
                'installroot' => array(
260
                    'shortopt' => 'R',
261
                    'arg' => 'DIR',
262
                    'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
263
                    ),
264
                'ignore-errors' => array(
265
                    'doc' => 'force install even if there were errors',
266
                    ),
267
                'offline' => array(
268
                    'shortopt' => 'O',
269
                    'doc' => 'do not attempt to uninstall remotely',
270
                    ),
271
                ),
272
            'doc' => '[channel/]<package> ...
273
Uninstalls one or more PEAR packages.  More than one package may be
274
specified at once.  Prefix with channel name to uninstall from a
275
channel not in your default channel ({config default_channel})
276
'),
277
        'bundle' => array(
278
            'summary' => 'Unpacks a Pecl Package',
279
            'function' => 'doBundle',
280
            'shortcut' => 'bun',
281
            'options' => array(
282
                'destination' => array(
283
                   'shortopt' => 'd',
284
                    'arg' => 'DIR',
285
                    'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
286
                    ),
287
                'force' => array(
288
                    'shortopt' => 'f',
289
                    'doc' => 'Force the unpacking even if there were errors in the package',
290
                ),
291
            ),
292
            'doc' => '<package>
293
Unpacks a Pecl Package into the selected location. It will download the
294
package if needed.
295
'),
296
        'run-scripts' => array(
297
            'summary' => 'Run Post-Install Scripts bundled with a package',
298
            'function' => 'doRunScripts',
299
            'shortcut' => 'rs',
300
            'options' => array(
301
            ),
302
            'doc' => '<package>
303
Run post-installation scripts in package <package>, if any exist.
304
'),
305
    );
306
 
307
    // }}}
308
    // {{{ constructor
309
 
310
    /**
311
     * PEAR_Command_Install constructor.
312
     *
313
     * @access public
314
     */
187 mathias 315
    function __construct(&$ui, &$config)
94 jpm 316
    {
187 mathias 317
        parent::__construct($ui, $config);
94 jpm 318
    }
319
 
320
    // }}}
321
 
322
    /**
323
     * For unit testing purposes
324
     */
325
    function &getDownloader(&$ui, $options, &$config)
326
    {
327
        if (!class_exists('PEAR_Downloader')) {
328
            require_once 'PEAR/Downloader.php';
329
        }
187 mathias 330
        $a = new PEAR_Downloader($ui, $options, $config);
94 jpm 331
        return $a;
332
    }
333
 
334
    /**
335
     * For unit testing purposes
336
     */
337
    function &getInstaller(&$ui)
338
    {
339
        if (!class_exists('PEAR_Installer')) {
340
            require_once 'PEAR/Installer.php';
341
        }
187 mathias 342
        $a = new PEAR_Installer($ui);
94 jpm 343
        return $a;
344
    }
345
 
346
    function enableExtension($binaries, $type)
347
    {
348
        if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
349
            return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
350
        }
351
        $ini = $this->_parseIni($phpini);
352
        if (PEAR::isError($ini)) {
353
            return $ini;
354
        }
355
        $line = 0;
356
        if ($type == 'extsrc' || $type == 'extbin') {
357
            $search = 'extensions';
358
            $enable = 'extension';
359
        } else {
360
            $search = 'zend_extensions';
361
            ob_start();
362
            phpinfo(INFO_GENERAL);
363
            $info = ob_get_contents();
364
            ob_end_clean();
365
            $debug = function_exists('leak') ? '_debug' : '';
187 mathias 366
            $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
94 jpm 367
            $enable = 'zend_extension' . $debug . $ts;
368
        }
369
        foreach ($ini[$search] as $line => $extension) {
370
            if (in_array($extension, $binaries, true) || in_array(
371
                  $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
372
                // already enabled - assume if one is, all are
373
                return true;
374
            }
375
        }
376
        if ($line) {
377
            $newini = array_slice($ini['all'], 0, $line);
378
        } else {
379
            $newini = array();
380
        }
381
        foreach ($binaries as $binary) {
382
            if ($ini['extension_dir']) {
383
                $binary = basename($binary);
384
            }
385
            $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
386
        }
387
        $newini = array_merge($newini, array_slice($ini['all'], $line));
187 mathias 388
        $fp = @fopen($phpini, 'wb');
389
        if (!$fp) {
390
            return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
391
        }
94 jpm 392
        foreach ($newini as $line) {
393
            fwrite($fp, $line);
394
        }
395
        fclose($fp);
396
        return true;
397
    }
398
 
399
    function disableExtension($binaries, $type)
400
    {
401
        if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
402
            return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
403
        }
404
        $ini = $this->_parseIni($phpini);
405
        if (PEAR::isError($ini)) {
406
            return $ini;
407
        }
408
        $line = 0;
409
        if ($type == 'extsrc' || $type == 'extbin') {
410
            $search = 'extensions';
411
            $enable = 'extension';
412
        } else {
413
            $search = 'zend_extensions';
414
            ob_start();
415
            phpinfo(INFO_GENERAL);
416
            $info = ob_get_contents();
417
            ob_end_clean();
418
            $debug = function_exists('leak') ? '_debug' : '';
187 mathias 419
            $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
94 jpm 420
            $enable = 'zend_extension' . $debug . $ts;
421
        }
422
        $found = false;
423
        foreach ($ini[$search] as $line => $extension) {
424
            if (in_array($extension, $binaries, true) || in_array(
425
                  $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
426
                $found = true;
427
                break;
428
            }
429
        }
430
        if (!$found) {
431
            // not enabled
432
            return true;
433
        }
434
        $fp = @fopen($phpini, 'wb');
435
        if (!$fp) {
436
            return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
437
        }
438
        if ($line) {
439
            $newini = array_slice($ini['all'], 0, $line);
440
            // delete the enable line
441
            $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
442
        } else {
443
            $newini = array_slice($ini['all'], 1);
444
        }
445
        foreach ($newini as $line) {
446
            fwrite($fp, $line);
447
        }
448
        fclose($fp);
449
        return true;
450
    }
451
 
452
    function _parseIni($filename)
453
    {
187 mathias 454
        if (!file_exists($filename)) {
455
            return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
456
        }
457
 
458
        if (filesize($filename) > 300000) {
459
            return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
460
        }
461
 
462
        ob_start();
463
        phpinfo(INFO_GENERAL);
464
        $info = ob_get_contents();
465
        ob_end_clean();
466
        $debug = function_exists('leak') ? '_debug' : '';
467
        $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
468
        $zend_extension_line = 'zend_extension' . $debug . $ts;
469
        $all = @file($filename);
470
        if ($all === false) {
471
            return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
472
        }
473
        $zend_extensions = $extensions = array();
474
        // assume this is right, but pull from the php.ini if it is found
475
        $extension_dir = ini_get('extension_dir');
476
        foreach ($all as $linenum => $line) {
477
            $line = trim($line);
478
            if (!$line) {
479
                continue;
94 jpm 480
            }
187 mathias 481
            if ($line[0] == ';') {
482
                continue;
94 jpm 483
            }
187 mathias 484
            if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
485
                $line = trim(substr($line, 13));
486
                if ($line[0] == '=') {
487
                    $x = trim(substr($line, 1));
488
                    $x = explode(';', $x);
489
                    $extension_dir = str_replace('"', '', array_shift($x));
94 jpm 490
                    continue;
491
                }
187 mathias 492
            }
493
            if (strtolower(substr($line, 0, 9)) == 'extension') {
494
                $line = trim(substr($line, 9));
495
                if ($line[0] == '=') {
496
                    $x = trim(substr($line, 1));
497
                    $x = explode(';', $x);
498
                    $extensions[$linenum] = str_replace('"', '', array_shift($x));
94 jpm 499
                    continue;
500
                }
187 mathias 501
            }
502
            if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
503
                  $zend_extension_line) {
504
                $line = trim(substr($line, strlen($zend_extension_line)));
505
                if ($line[0] == '=') {
506
                    $x = trim(substr($line, 1));
507
                    $x = explode(';', $x);
508
                    $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
509
                    continue;
94 jpm 510
                }
511
            }
512
        }
187 mathias 513
        return array(
514
            'extensions' => $extensions,
515
            'zend_extensions' => $zend_extensions,
516
            'extension_dir' => $extension_dir,
517
            'all' => $all,
518
        );
94 jpm 519
    }
520
 
521
    // {{{ doInstall()
522
 
523
    function doInstall($command, $options, $params)
524
    {
187 mathias 525
        if (!class_exists('PEAR_PackageFile')) {
526
            require_once 'PEAR/PackageFile.php';
527
        }
528
 
529
        if (isset($options['installroot']) && isset($options['packagingroot'])) {
530
            return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
531
        }
532
 
533
        $reg = &$this->config->getRegistry();
534
        $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
535
        if (!$reg->channelExists($channel)) {
536
            return $this->raiseError('Channel "' . $channel . '" does not exist');
537
        }
538
 
94 jpm 539
        if (empty($this->installer)) {
540
            $this->installer = &$this->getInstaller($this->ui);
541
        }
187 mathias 542
 
543
        if ($command == 'upgrade' || $command == 'upgrade-all') {
544
            // If people run the upgrade command but pass nothing, emulate a upgrade-all
545
            if ($command == 'upgrade' && empty($params)) {
546
                return $this->doUpgradeAll($command, $options, $params);
547
            }
94 jpm 548
            $options['upgrade'] = true;
187 mathias 549
        } else {
550
            $packages = $params;
94 jpm 551
        }
187 mathias 552
 
553
        $instreg = &$reg; // instreg used to check if package is installed
554
        if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
555
            $packrootphp_dir = $this->installer->_prependPath(
556
                $this->config->get('php_dir', null, 'pear.php.net'),
557
                $options['packagingroot']);
558
            $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net');
559
            if ($metadata_dir) {
560
                $metadata_dir = $this->installer->_prependPath(
561
                    $metadata_dir,
562
                    $options['packagingroot']);
563
            }
564
            $instreg = new PEAR_Registry($packrootphp_dir, false, false, $metadata_dir); // other instreg!
565
 
566
            if ($this->config->get('verbose') > 2) {
567
                $this->ui->outputData('using package root: ' . $options['packagingroot']);
568
            }
94 jpm 569
        }
187 mathias 570
 
571
        $abstractpackages = $otherpackages = array();
572
        // parse params
573
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
574
 
575
        foreach ($params as $param) {
576
            if (strpos($param, 'http://') === 0) {
577
                $otherpackages[] = $param;
578
                continue;
579
            }
580
 
581
            if (strpos($param, 'channel://') === false && @file_exists($param)) {
582
                if (isset($options['force'])) {
583
                    $otherpackages[] = $param;
94 jpm 584
                    continue;
585
                }
187 mathias 586
 
587
                $pkg = new PEAR_PackageFile($this->config);
588
                $pf  = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
589
                if (PEAR::isError($pf)) {
590
                    $otherpackages[] = $param;
591
                    continue;
94 jpm 592
                }
187 mathias 593
 
594
                $exists   = $reg->packageExists($pf->getPackage(), $pf->getChannel());
595
                $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
596
                $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
597
                if ($exists && $version_compare) {
598
                    if ($this->config->get('verbose')) {
599
                        $this->ui->outputData('Ignoring installed package ' .
600
                            $reg->parsedPackageNameToString(
601
                            array('package' => $pf->getPackage(),
602
                                  'channel' => $pf->getChannel()), true));
94 jpm 603
                    }
604
                    continue;
605
                }
187 mathias 606
                $otherpackages[] = $param;
607
                continue;
608
            }
609
 
610
            $e = $reg->parsePackageName($param, $channel);
611
            if (PEAR::isError($e)) {
612
                $otherpackages[] = $param;
613
            } else {
614
                $abstractpackages[] = $e;
615
            }
616
        }
617
        PEAR::staticPopErrorHandling();
618
 
619
        // if there are any local package .tgz or remote static url, we can't
620
        // filter.  The filter only works for abstract packages
621
        if (count($abstractpackages) && !isset($options['force'])) {
622
            // when not being forced, only do necessary upgrades/installs
623
            if (isset($options['upgrade'])) {
624
                $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
625
            } else {
626
                $count = count($abstractpackages);
627
                foreach ($abstractpackages as $i => $package) {
628
                    if (isset($package['group'])) {
629
                        // do not filter out install groups
94 jpm 630
                        continue;
631
                    }
187 mathias 632
 
633
                    if ($instreg->packageExists($package['package'], $package['channel'])) {
634
                        if ($count > 1) {
635
                            if ($this->config->get('verbose')) {
636
                                $this->ui->outputData('Ignoring installed package ' .
637
                                    $reg->parsedPackageNameToString($package, true));
638
                            }
639
                            unset($abstractpackages[$i]);
640
                        } elseif ($count === 1) {
641
                            // Lets try to upgrade it since it's already installed
642
                            $options['upgrade'] = true;
643
                        }
94 jpm 644
                    }
645
                }
646
            }
187 mathias 647
            $abstractpackages =
648
                array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
649
        } elseif (count($abstractpackages)) {
650
            $abstractpackages =
651
                array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
94 jpm 652
        }
187 mathias 653
 
654
        $packages = array_merge($abstractpackages, $otherpackages);
655
        if (!count($packages)) {
656
            $c = '';
657
            if (isset($options['channel'])){
658
                $c .= ' in channel "' . $options['channel'] . '"';
659
            }
660
            $this->ui->outputData('Nothing to ' . $command . $c);
661
            return true;
662
        }
663
 
94 jpm 664
        $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
187 mathias 665
        $errors = $downloaded = $binaries = array();
666
        $downloaded = &$this->downloader->download($packages);
94 jpm 667
        if (PEAR::isError($downloaded)) {
668
            return $this->raiseError($downloaded);
669
        }
187 mathias 670
 
94 jpm 671
        $errors = $this->downloader->getErrorMsgs();
672
        if (count($errors)) {
187 mathias 673
            $err = array();
94 jpm 674
            $err['data'] = array();
675
            foreach ($errors as $error) {
187 mathias 676
                if ($error !== null) {
677
                    $err['data'][] = array($error);
678
                }
94 jpm 679
            }
187 mathias 680
 
681
            if (!empty($err['data'])) {
682
                $err['headline'] = 'Install Errors';
683
                $this->ui->outputData($err);
684
            }
685
 
94 jpm 686
            if (!count($downloaded)) {
687
                return $this->raiseError("$command failed");
688
            }
689
        }
187 mathias 690
 
94 jpm 691
        $data = array(
692
            'headline' => 'Packages that would be Installed'
693
        );
187 mathias 694
 
94 jpm 695
        if (isset($options['pretend'])) {
696
            foreach ($downloaded as $package) {
697
                $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
698
            }
699
            $this->ui->outputData($data, 'pretend');
700
            return true;
701
        }
187 mathias 702
 
94 jpm 703
        $this->installer->setOptions($options);
704
        $this->installer->sortPackagesForInstall($downloaded);
705
        if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
706
            $this->raiseError($err->getMessage());
707
            return true;
708
        }
187 mathias 709
 
710
        $binaries = $extrainfo = array();
94 jpm 711
        foreach ($downloaded as $param) {
712
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
713
            $info = $this->installer->install($param, $options);
714
            PEAR::staticPopErrorHandling();
715
            if (PEAR::isError($info)) {
716
                $oldinfo = $info;
717
                $pkg = &$param->getPackageFile();
718
                if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
719
                    if (!($info = $pkg->installBinary($this->installer))) {
720
                        $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
721
                        continue;
722
                    }
187 mathias 723
 
94 jpm 724
                    // we just installed a different package than requested,
725
                    // let's change the param and info so that the rest of this works
726
                    $param = $info[0];
187 mathias 727
                    $info  = $info[1];
94 jpm 728
                }
729
            }
187 mathias 730
 
731
            if (!is_array($info)) {
732
                return $this->raiseError("$command failed");
733
            }
734
 
735
            if ($param->getPackageType() == 'extsrc' ||
736
                  $param->getPackageType() == 'extbin' ||
737
                  $param->getPackageType() == 'zendextsrc' ||
738
                  $param->getPackageType() == 'zendextbin'
739
            ) {
740
                $pkg = &$param->getPackageFile();
741
                if ($instbin = $pkg->getInstalledBinary()) {
742
                    $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
743
                } else {
744
                    $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
745
                }
746
 
747
                foreach ($instpkg->getFilelist() as $name => $atts) {
748
                    $pinfo = pathinfo($atts['installed_as']);
749
                    if (!isset($pinfo['extension']) ||
750
                          in_array($pinfo['extension'], array('c', 'h'))
751
                    ) {
752
                        continue; // make sure we don't match php_blah.h
94 jpm 753
                    }
187 mathias 754
 
755
                    if ((strpos($pinfo['basename'], 'php_') === 0 &&
756
                          $pinfo['extension'] == 'dll') ||
757
                          // most unices
758
                          $pinfo['extension'] == 'so' ||
759
                          // hp-ux
760
                          $pinfo['extension'] == 'sl') {
761
                        $binaries[] = array($atts['installed_as'], $pinfo);
762
                        break;
94 jpm 763
                    }
187 mathias 764
                }
765
 
766
                if (count($binaries)) {
94 jpm 767
                    foreach ($binaries as $pinfo) {
768
                        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
769
                        $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
770
                        PEAR::staticPopErrorHandling();
771
                        if (PEAR::isError($ret)) {
772
                            $extrainfo[] = $ret->getMessage();
773
                            if ($param->getPackageType() == 'extsrc' ||
774
                                  $param->getPackageType() == 'extbin') {
775
                                $exttype = 'extension';
187 mathias 776
                                $extpath = $pinfo[1]['basename'];
94 jpm 777
                            } else {
187 mathias 778
                                $exttype = 'zend_extension';
779
                                $extpath = $atts['installed_as'];
94 jpm 780
                            }
781
                            $extrainfo[] = 'You should add "' . $exttype . '=' .
187 mathias 782
                                $extpath . '" to php.ini';
94 jpm 783
                        } else {
784
                            $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
785
                                ' enabled in php.ini';
786
                        }
787
                    }
788
                }
187 mathias 789
            }
790
 
791
            if ($this->config->get('verbose') > 0) {
792
                $chan = $param->getChannel();
793
                $label = $reg->parsedPackageNameToString(
794
                    array(
795
                        'channel' => $chan,
796
                        'package' => $param->getPackage(),
797
                        'version' => $param->getVersion(),
798
                    ));
799
                $out = array('data' => "$command ok: $label");
800
                if (isset($info['release_warnings'])) {
801
                    $out['release_warnings'] = $info['release_warnings'];
802
                }
803
                $this->ui->outputData($out, $command);
804
 
805
                if (!isset($options['register-only']) && !isset($options['offline'])) {
806
                    if ($this->config->isDefinedLayer('ftp')) {
807
                        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
808
                        $info = $this->installer->ftpInstall($param);
809
                        PEAR::staticPopErrorHandling();
810
                        if (PEAR::isError($info)) {
811
                            $this->ui->outputData($info->getMessage());
812
                            $this->ui->outputData("remote install failed: $label");
813
                        } else {
814
                            $this->ui->outputData("remote install ok: $label");
94 jpm 815
                        }
816
                    }
817
                }
187 mathias 818
            }
819
 
820
            $deps = $param->getDeps();
821
            if ($deps) {
822
                if (isset($deps['group'])) {
823
                    $groups = $deps['group'];
824
                    if (!isset($groups[0])) {
825
                        $groups = array($groups);
826
                    }
827
 
828
                    foreach ($groups as $group) {
829
                        if ($group['attribs']['name'] == 'default') {
830
                            // default group is always installed, unless the user
831
                            // explicitly chooses to install another group
832
                            continue;
94 jpm 833
                        }
187 mathias 834
                        $extrainfo[] = $param->getPackage() . ': Optional feature ' .
835
                            $group['attribs']['name'] . ' available (' .
836
                            $group['attribs']['hint'] . ')';
94 jpm 837
                    }
187 mathias 838
 
839
                    $extrainfo[] = $param->getPackage() .
840
                        ': To install optional features use "pear install ' .
841
                        $reg->parsedPackageNameToString(
842
                            array('package' => $param->getPackage(),
843
                                  'channel' => $param->getChannel()), true) .
844
                              '#featurename"';
94 jpm 845
                }
187 mathias 846
            }
847
 
848
            $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
849
            // $pkg may be NULL if install is a 'fake' install via --packagingroot
850
            if (is_object($pkg)) {
851
                $pkg->setConfig($this->config);
852
                if ($list = $pkg->listPostinstallScripts()) {
853
                    $pn = $reg->parsedPackageNameToString(array('channel' =>
854
                       $param->getChannel(), 'package' => $param->getPackage()), true);
855
                    $extrainfo[] = $pn . ' has post-install scripts:';
856
                    foreach ($list as $file) {
857
                        $extrainfo[] = $file;
94 jpm 858
                    }
187 mathias 859
                    $extrainfo[] = $param->getPackage() .
860
                        ': Use "pear run-scripts ' . $pn . '" to finish setup.';
861
                    $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
94 jpm 862
                }
863
            }
864
        }
187 mathias 865
 
94 jpm 866
        if (count($extrainfo)) {
867
            foreach ($extrainfo as $info) {
868
                $this->ui->outputData($info);
869
            }
870
        }
187 mathias 871
 
94 jpm 872
        return true;
873
    }
874
 
875
    // }}}
187 mathias 876
    // {{{ doUpgradeAll()
877
 
878
    function doUpgradeAll($command, $options, $params)
879
    {
880
        $reg = &$this->config->getRegistry();
881
        $upgrade = array();
882
 
883
        if (isset($options['channel'])) {
884
            $channels = array($options['channel']);
885
        } else {
886
            $channels = $reg->listChannels();
887
        }
888
 
889
        foreach ($channels as $channel) {
890
            if ($channel == '__uri') {
891
                continue;
892
            }
893
 
894
            // parse name with channel
895
            foreach ($reg->listPackages($channel) as $name) {
896
                $upgrade[] = $reg->parsedPackageNameToString(array(
897
                        'channel' => $channel,
898
                        'package' => $name
899
                    ));
900
            }
901
        }
902
 
903
        $err = $this->doInstall($command, $options, $upgrade);
904
        if (PEAR::isError($err)) {
905
            $this->ui->outputData($err->getMessage(), $command);
906
        }
907
   }
908
 
909
    // }}}
94 jpm 910
    // {{{ doUninstall()
911
 
912
    function doUninstall($command, $options, $params)
913
    {
187 mathias 914
        if (count($params) < 1) {
915
            return $this->raiseError("Please supply the package(s) you want to uninstall");
916
        }
917
 
94 jpm 918
        if (empty($this->installer)) {
919
            $this->installer = &$this->getInstaller($this->ui);
920
        }
187 mathias 921
 
94 jpm 922
        if (isset($options['remoteconfig'])) {
923
            $e = $this->config->readFTPConfigFile($options['remoteconfig']);
924
            if (!PEAR::isError($e)) {
925
                $this->installer->setConfig($this->config);
926
            }
927
        }
187 mathias 928
 
94 jpm 929
        $reg = &$this->config->getRegistry();
930
        $newparams = array();
187 mathias 931
        $binaries = array();
94 jpm 932
        $badparams = array();
933
        foreach ($params as $pkg) {
934
            $channel = $this->config->get('default_channel');
935
            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
936
            $parsed = $reg->parsePackageName($pkg, $channel);
937
            PEAR::staticPopErrorHandling();
938
            if (!$parsed || PEAR::isError($parsed)) {
939
                $badparams[] = $pkg;
940
                continue;
941
            }
942
            $package = $parsed['package'];
943
            $channel = $parsed['channel'];
944
            $info = &$reg->getPackage($package, $channel);
945
            if ($info === null &&
946
                 ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
947
                // make sure this isn't a package that has flipped from pear to pecl but
948
                // used a package.xml 1.0
949
                $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
950
                $info = &$reg->getPackage($package, $testc);
951
                if ($info !== null) {
952
                    $channel = $testc;
953
                }
954
            }
955
            if ($info === null) {
956
                $badparams[] = $pkg;
957
            } else {
958
                $newparams[] = &$info;
959
                // check for binary packages (this is an alias for those packages if so)
960
                if ($installedbinary = $info->getInstalledBinary()) {
961
                    $this->ui->log('adding binary package ' .
962
                        $reg->parsedPackageNameToString(array('channel' => $channel,
963
                            'package' => $installedbinary), true));
964
                    $newparams[] = &$reg->getPackage($installedbinary, $channel);
965
                }
966
                // add the contents of a dependency group to the list of installed packages
967
                if (isset($parsed['group'])) {
968
                    $group = $info->getDependencyGroup($parsed['group']);
969
                    if ($group) {
187 mathias 970
                        $installed = $reg->getInstalledGroup($group);
94 jpm 971
                        if ($installed) {
972
                            foreach ($installed as $i => $p) {
973
                                $newparams[] = &$installed[$i];
974
                            }
975
                        }
976
                    }
977
                }
978
            }
979
        }
980
        $err = $this->installer->sortPackagesForUninstall($newparams);
981
        if (PEAR::isError($err)) {
982
            $this->ui->outputData($err->getMessage(), $command);
983
            return true;
984
        }
985
        $params = $newparams;
986
        // twist this to use it to check on whether dependent packages are also being uninstalled
987
        // for circular dependencies like subpackages
988
        $this->installer->setUninstallPackages($newparams);
989
        $params = array_merge($params, $badparams);
187 mathias 990
        $binaries = array();
94 jpm 991
        foreach ($params as $pkg) {
992
            $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
993
            if ($err = $this->installer->uninstall($pkg, $options)) {
994
                $this->installer->popErrorHandling();
995
                if (PEAR::isError($err)) {
996
                    $this->ui->outputData($err->getMessage(), $command);
997
                    continue;
998
                }
999
                if ($pkg->getPackageType() == 'extsrc' ||
1000
                      $pkg->getPackageType() == 'extbin' ||
1001
                      $pkg->getPackageType() == 'zendextsrc' ||
1002
                      $pkg->getPackageType() == 'zendextbin') {
1003
                    if ($instbin = $pkg->getInstalledBinary()) {
1004
                        continue; // this will be uninstalled later
1005
                    }
187 mathias 1006
 
94 jpm 1007
                    foreach ($pkg->getFilelist() as $name => $atts) {
1008
                        $pinfo = pathinfo($atts['installed_as']);
1009
                        if (!isset($pinfo['extension']) ||
1010
                              in_array($pinfo['extension'], array('c', 'h'))) {
1011
                            continue; // make sure we don't match php_blah.h
1012
                        }
1013
                        if ((strpos($pinfo['basename'], 'php_') === 0 &&
1014
                              $pinfo['extension'] == 'dll') ||
1015
                              // most unices
1016
                              $pinfo['extension'] == 'so' ||
1017
                              // hp-ux
1018
                              $pinfo['extension'] == 'sl') {
1019
                            $binaries[] = array($atts['installed_as'], $pinfo);
1020
                            break;
1021
                        }
1022
                    }
187 mathias 1023
                    if (count($binaries)) {
1024
                        foreach ($binaries as $pinfo) {
1025
                            PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1026
                            $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
1027
                            PEAR::staticPopErrorHandling();
1028
                            if (PEAR::isError($ret)) {
1029
                                $extrainfo[] = $ret->getMessage();
1030
                                if ($pkg->getPackageType() == 'extsrc' ||
1031
                                      $pkg->getPackageType() == 'extbin') {
1032
                                    $exttype = 'extension';
1033
                                } else {
1034
                                    ob_start();
1035
                                    phpinfo(INFO_GENERAL);
1036
                                    $info = ob_get_contents();
1037
                                    ob_end_clean();
1038
                                    $debug = function_exists('leak') ? '_debug' : '';
1039
                                    $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
1040
                                    $exttype = 'zend_extension' . $debug . $ts;
1041
                                }
1042
                                $this->ui->outputData('Unable to remove "' . $exttype . '=' .
1043
                                    $pinfo[1]['basename'] . '" from php.ini', $command);
94 jpm 1044
                            } else {
187 mathias 1045
                                $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
1046
                                    ' disabled in php.ini', $command);
94 jpm 1047
                            }
1048
                        }
1049
                    }
1050
                }
1051
                $savepkg = $pkg;
1052
                if ($this->config->get('verbose') > 0) {
1053
                    if (is_object($pkg)) {
1054
                        $pkg = $reg->parsedPackageNameToString($pkg);
1055
                    }
1056
                    $this->ui->outputData("uninstall ok: $pkg", $command);
1057
                }
1058
                if (!isset($options['offline']) && is_object($savepkg) &&
1059
                      defined('PEAR_REMOTEINSTALL_OK')) {
1060
                    if ($this->config->isDefinedLayer('ftp')) {
1061
                        $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
1062
                        $info = $this->installer->ftpUninstall($savepkg);
1063
                        $this->installer->popErrorHandling();
1064
                        if (PEAR::isError($info)) {
1065
                            $this->ui->outputData($info->getMessage());
1066
                            $this->ui->outputData("remote uninstall failed: $pkg");
1067
                        } else {
1068
                            $this->ui->outputData("remote uninstall ok: $pkg");
1069
                        }
1070
                    }
1071
                }
1072
            } else {
1073
                $this->installer->popErrorHandling();
187 mathias 1074
                if (!is_object($pkg)) {
1075
                    return $this->raiseError("uninstall failed: $pkg");
94 jpm 1076
                }
187 mathias 1077
                $pkg = $reg->parsedPackageNameToString($pkg);
94 jpm 1078
            }
1079
        }
187 mathias 1080
 
94 jpm 1081
        return true;
1082
    }
1083
 
1084
    // }}}
1085
 
1086
 
1087
    // }}}
1088
    // {{{ doBundle()
1089
    /*
1090
    (cox) It just downloads and untars the package, does not do
1091
            any check that the PEAR_Installer::_installFile() does.
1092
    */
1093
 
1094
    function doBundle($command, $options, $params)
1095
    {
187 mathias 1096
        $opts = array(
1097
            'force'        => true,
1098
            'nodeps'       => true,
1099
            'soft'         => true,
1100
            'downloadonly' => true
1101
        );
1102
        $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
94 jpm 1103
        $reg = &$this->config->getRegistry();
187 mathias 1104
        if (count($params) < 1) {
94 jpm 1105
            return $this->raiseError("Please supply the package you want to bundle");
1106
        }
1107
 
1108
        if (isset($options['destination'])) {
1109
            if (!is_dir($options['destination'])) {
1110
                System::mkdir('-p ' . $options['destination']);
1111
            }
1112
            $dest = realpath($options['destination']);
1113
        } else {
187 mathias 1114
            $pwd  = getcwd();
1115
            $dir  = $pwd . DIRECTORY_SEPARATOR . 'ext';
1116
            $dest = is_dir($dir) ? $dir : $pwd;
94 jpm 1117
        }
187 mathias 1118
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1119
        $err = $downloader->setDownloadDir($dest);
1120
        PEAR::staticPopErrorHandling();
1121
        if (PEAR::isError($err)) {
1122
            return PEAR::raiseError('download directory "' . $dest .
1123
                '" is not writeable.');
1124
        }
94 jpm 1125
        $result = &$downloader->download(array($params[0]));
1126
        if (PEAR::isError($result)) {
1127
            return $result;
1128
        }
187 mathias 1129
        if (!isset($result[0])) {
1130
            return $this->raiseError('unable to unpack ' . $params[0]);
1131
        }
94 jpm 1132
        $pkgfile = &$result[0]->getPackageFile();
1133
        $pkgname = $pkgfile->getName();
1134
        $pkgversion = $pkgfile->getVersion();
1135
 
1136
        // Unpacking -------------------------------------------------
1137
        $dest .= DIRECTORY_SEPARATOR . $pkgname;
1138
        $orig = $pkgname . '-' . $pkgversion;
1139
 
187 mathias 1140
        $tar = new Archive_Tar($pkgfile->getArchiveFile());
94 jpm 1141
        if (!$tar->extractModify($dest, $orig)) {
1142
            return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
1143
        }
1144
        $this->ui->outputData("Package ready at '$dest'");
1145
    // }}}
1146
    }
1147
 
1148
    // }}}
1149
 
1150
    function doRunScripts($command, $options, $params)
1151
    {
1152
        if (!isset($params[0])) {
1153
            return $this->raiseError('run-scripts expects 1 parameter: a package name');
1154
        }
187 mathias 1155
 
94 jpm 1156
        $reg = &$this->config->getRegistry();
1157
        PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1158
        $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
1159
        PEAR::staticPopErrorHandling();
1160
        if (PEAR::isError($parsed)) {
1161
            return $this->raiseError($parsed);
1162
        }
187 mathias 1163
 
94 jpm 1164
        $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
187 mathias 1165
        if (!is_object($package)) {
94 jpm 1166
            return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
1167
        }
187 mathias 1168
 
1169
        $package->setConfig($this->config);
1170
        $package->runPostinstallScripts();
94 jpm 1171
        $this->ui->outputData('Install scripts complete', $command);
1172
        return true;
1173
    }
187 mathias 1174
 
1175
    /**
1176
     * Given a list of packages, filter out those ones that are already up to date
1177
     *
1178
     * @param $packages: packages, in parsed array format !
1179
     * @return list of packages that can be upgraded
1180
     */
1181
    function _filterUptodatePackages($packages, $command)
1182
    {
1183
        $reg = &$this->config->getRegistry();
1184
        $latestReleases = array();
1185
 
1186
        $ret = array();
1187
        foreach ($packages as $package) {
1188
            if (isset($package['group'])) {
1189
                $ret[] = $package;
1190
                continue;
1191
            }
1192
 
1193
            $channel = $package['channel'];
1194
            $name    = $package['package'];
1195
            if (!$reg->packageExists($name, $channel)) {
1196
                $ret[] = $package;
1197
                continue;
1198
            }
1199
 
1200
            if (!isset($latestReleases[$channel])) {
1201
                // fill in cache for this channel
1202
                $chan = $reg->getChannel($channel);
1203
                if (PEAR::isError($chan)) {
1204
                    return $this->raiseError($chan);
1205
                }
1206
 
1207
                $base2 = false;
1208
                $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
1209
                if ($chan->supportsREST($preferred_mirror) &&
1210
                    (
1211
                       //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
1212
                       ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
1213
                    )
1214
                ) {
1215
                    $dorest = true;
1216
                }
1217
 
1218
                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1219
                if (!isset($package['state'])) {
1220
                    $state = $this->config->get('preferred_state', null, $channel);
1221
                } else {
1222
                    $state = $package['state'];
1223
                }
1224
 
1225
                if ($dorest) {
1226
                    if ($base2) {
1227
                        $rest = &$this->config->getREST('1.4', array());
1228
                        $base = $base2;
1229
                    } else {
1230
                        $rest = &$this->config->getREST('1.0', array());
1231
                    }
1232
 
1233
                    $installed = array_flip($reg->listPackages($channel));
1234
                    $latest    = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
1235
                }
1236
 
1237
                PEAR::staticPopErrorHandling();
1238
                if (PEAR::isError($latest)) {
1239
                    $this->ui->outputData('Error getting channel info from ' . $channel .
1240
                        ': ' . $latest->getMessage());
1241
                    continue;
1242
                }
1243
 
1244
                $latestReleases[$channel] = array_change_key_case($latest);
1245
            }
1246
 
1247
            // check package for latest release
1248
            $name_lower = strtolower($name);
1249
            if (isset($latestReleases[$channel][$name_lower])) {
1250
                // if not set, up to date
1251
                $inst_version    = $reg->packageInfo($name, 'version', $channel);
1252
                $channel_version = $latestReleases[$channel][$name_lower]['version'];
1253
                if (version_compare($channel_version, $inst_version, 'le')) {
1254
                    // installed version is up-to-date
1255
                    continue;
1256
                }
1257
 
1258
                // maintain BC
1259
                if ($command == 'upgrade-all') {
1260
                    $this->ui->outputData(array('data' => 'Will upgrade ' .
1261
                        $reg->parsedPackageNameToString($package)), $command);
1262
                }
1263
                $ret[] = $package;
1264
            }
1265
        }
1266
 
1267
        return $ret;
1268
    }
94 jpm 1269
}