package - create a packaged release in phar, tar, tgz or zip format

Introduction

The package command is available through the developer tools. If you do not have the developer tools installed, simply run
php pyrus.phar package
and Pyrus will ask if you would like to install the developer tools. If you assent with the word yes, Pyrus will automatically download them and install them for you.

The package command bundles up the files of a package and its package.xml into an archive for distribution. It accepts a single optional argument, the path to a package.xml.

If the optional path is not provided, the command searches for a file named package.xml in the current directory. If this file is an older version 1.0, it also searches for package2.xml in the current directory, and uses that as the package file. This allows creating packages that are compatible with ancient versions of PEAR older than version 1.4.0

If package.xml exists and is a PEAR2 package (requires pear installer version equal to or newer than 2.0.0a1), the command will also look for a file in the current directory named package_compatible.xml. This file should be a package.xml customized for use by the PEAR Installer, and is automatically generated by the make command unless explicitly prevented. This file makes it possible for the PEAR Installer to install packages generated for Pyrus.

The created archive can be in any or all of the following formats:

  1. phar
  2. tar
  3. tgz
  4. zip

The formats are requested by passing their name as an option like so:

php pyrus.phar package --phar --tar --tgz --zip

.

The phar file format is a format that can be used to create self-installing archives, or even archives that are self-contained commands. pyrus.phar, for instance, is a complete application that runs directly from its archive. Due to security considerations, the ability to create executable phar archives is disabled by default. To create a phar archive, the phar.readonly php.ini setting must be disabled like so:

php -dphar.readonly=0 pyrus.phar package --phar

The tar and tgz file formats are the formats familiar to users of PEAR. tgz is a gzipped tar archive, and requires the zlib extension be enabled in order to create it.

The zip file format is most familiar to Windows users.

PEAR2 packages

All packages designed for Pyrus automatically have PEAR2/Autoload.php, PEAR2/Exception.php, PEAR2/MultiErrors.php, and PEAR2/MultiErrors/Exception.php bundled so that these dependencies are available when a package is extracted without use of Pyrus to install it. Packages designed for installation by the PEAR Installer and not for Pyrus do not bundle any dependencies.

Package signing

Pyrus supports creating archives that have a mandatory signature using OpenSSL certificates such as those available from CACert. Signed archives cannot be processed without the presence of the openssl PHP extension. In addition, a bug in the phar extension's verification of openssl signatures requires PHP version 5.3.1 or newer. Creation of signatures only requires PHP version 5.3.0 or newer.

To create a package signature, set the openssl_cert configuration variable to the path of your PKCS#12 certificate (generally saved with a file extension of p12), and the handle configuration variable to your handle in package.xml.

--stub

The --stub or -s option specifies a PHP script to use as the stub to a phar archive, and is ignored if --phar is not passed to the command. The stub is a short executable script that is executed as a boot strap when a phar archive is passed to PHP like

php pyrus.phar

. All stubs must end with the __HALT_COMPILER(); directive to be a valid stub.

If the --stub option is not explicitly specified and a phar archive is being created, Pyrus will look for a file named stub.php in the same directory as the package.xml, and will use that as the stub for the phar archive if found.

Here is pyrus's stub:

<?php
if (version_compare(phpversion(), '5.3.0''<')) {
    if (
substr(phpversion(), 05) != '5.3.0') {
        
// this small hack is because of running RCs of 5.3.0
        
echo "Pyrus requires PHP 5.3.0 or newer.\n";
        exit -
1;
    }
}
foreach (array(
'phar''spl''pcre''simplexml') as $ext) {
    if (!
extension_loaded($ext)) {
        echo 
'Extension '$ext" is required\n";
        exit -
1;
    }
}
try {
    
Phar::mapPhar();
} catch (
Exception $e) {
    echo 
"Cannot process Pyrus phar:\n";
    echo 
$e->getMessage(), "\n";
    exit -
1;
}
function 
pyrus_autoload($class)
{
    
$class str_replace('_''\\'$class);
    if (
file_exists('phar://' __FILE__ '/php/' implode('/'explode('\\'$class)) . '.php')) {
        include 
'phar://' __FILE__ '/php/' implode('/'explode('\\'$class)) . '.php';
    }
}
spl_autoload_register("pyrus_autoload");
$frontend = new \PEAR2\Pyrus\ScriptFrontend\Commands;
@
array_shift($_SERVER['argv']);
$frontend->run($_SERVER['argv']);
__HALT_COMPILER();

--extrasetup

The --extrasetup or -e option is used to specify the path to a PHP script that is used to include files in the created packages that are not in the package.xml list of files. This is used to create archives that are designed to be friendly to users simply "trying before they buy" the archive, or to provide support files needed to create self-installing archives.

If the --extrasetup option is not explicitly specified, then Pyrus looks for a file named extrasetup.php in the same directory as the package.xml, and will use this if found.

The extrasetup script should create a variable named $extrafiles that contains an associative array mapping relative path within the archive to an absolute path of a file on disk.

Here is Pyrus's extrasetup, which demonstrates bundling of the required dependencies PEAR2_HTTP_Request and PEAR2_Console_Commandline:

<?php
/**
 * This file generates the pyrus.phar file and PEAR2 package for Pyrus.
 */
$rp __DIR__ '/../HTTP_Request/src/HTTP';
$cc __DIR__ '/../sandbox/Console_CommandLine/src/Console';
$extrafiles = array(
    
'php/PEAR2/HTTP/Request.php' => $rp '/Request.php',
    
'php/PEAR2/HTTP/Request/Adapter.php' => $rp '/Request/Adapter.php',
    
'php/PEAR2/HTTP/Request/Adapter/Curl.php' => $rp '/Request/Adapter/Curl.php',
    
'php/PEAR2/HTTP/Request/Adapter/Http.php' => $rp '/Request/Adapter/Http.php',
    
'php/PEAR2/HTTP/Request/Adapter/Phpsocket.php' => $rp '/Request/Adapter/Phpsocket.php',
    
'php/PEAR2/HTTP/Request/Adapter/Phpstream.php' => $rp '/Request/Adapter/Phpstream.php',
    
'php/PEAR2/HTTP/Request/Exception.php' => $rp '/Request/Exception.php',
    
'php/PEAR2/HTTP/Request/Headers.php' => $rp '/Request/Headers.php',
    
'php/PEAR2/HTTP/Request/Listener.php' => $rp '/Request/Listener.php',
    
'php/PEAR2/HTTP/Request/Response.php' => $rp '/Request/Response.php',
    
'php/PEAR2/HTTP/Request/Uri.php' => $rp '/Request/Uri.php',

    
'php/PEAR2/Console/CommandLine.php' => $cc '/CommandLine.php',
    
'php/PEAR2/Console/CommandLine/Result.php' => $cc '/CommandLine/Result.php',
    
'php/PEAR2/Console/CommandLine/Renderer.php' => $cc '/CommandLine/Renderer.php',
    
'php/PEAR2/Console/CommandLine/Outputter.php' => $cc '/CommandLine/Outputter.php',
    
'php/PEAR2/Console/CommandLine/Option.php' => $cc '/CommandLine/Option.php',
    
'php/PEAR2/Console/CommandLine/MessageProvider.php' => $cc '/CommandLine/MessageProvider.php',
    
'php/PEAR2/Console/CommandLine/Exception.php' => $cc '/CommandLine/Exception.php',
    
'php/PEAR2/Console/CommandLine/Element.php' => $cc '/CommandLine/Element.php',
    
'php/PEAR2/Console/CommandLine/Command.php' => $cc '/CommandLine/Command.php',
    
'php/PEAR2/Console/CommandLine/Argument.php' => $cc '/CommandLine/Argument.php',
    
'php/PEAR2/Console/CommandLine/Action.php' => $cc '/CommandLine/Action.php',
    
'php/PEAR2/Console/CommandLine/Renderer/Default.php' => $cc '/CommandLine/Renderer/Default.php',
    
'php/PEAR2/Console/CommandLine/Outputter/Default.php' => $cc '/CommandLine/Outputter/Default.php',
    
'php/PEAR2/Console/CommandLine/MessageProvider/Default.php' => $cc '/CommandLine/MessageProvider/Default.php',
    
'php/PEAR2/Console/CommandLine/Action/Callback.php' => $cc '/CommandLine/Action/Callback.php',
    
'php/PEAR2/Console/CommandLine/Action/Counter.php' => $cc '/CommandLine/Action/Counter.php',
    
'php/PEAR2/Console/CommandLine/Action/Help.php' => $cc '/CommandLine/Action/Help.php',
    
'php/PEAR2/Console/CommandLine/Action/StoreFloat.php' => $cc '/CommandLine/Action/StoreFloat.php',
    
'php/PEAR2/Console/CommandLine/Action/StoreInt.php' => $cc '/CommandLine/Action/StoreInt.php',
    
'php/PEAR2/Console/CommandLine/Action/StoreString.php' => $cc '/CommandLine/Action/StoreString.php',
    
'php/PEAR2/Console/CommandLine/Action/StoreTrue.php' => $cc '/CommandLine/Action/StoreTrue.php',
    
'php/PEAR2/Console/CommandLine/Action/Version.php' => $cc '/CommandLine/Action/Version.php',
);