PEAR_PackageFileManager : The Definitive Guide |
Copyright © 2006 Gregory Beaver, Laurent Laville
This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/.
| Revision History | |
|---|---|
| Revision 1.6.0 | November 17, 2006 |
| The first edition of this Guide is now completed. It cover version 1.6.0 (stable) of PEAR_PackageFileManager. | |
Table of Contents
List of Tables
package.xml
2.0
package.xml 1.0 dependencies
package.xml 2.0 dependencies
List of Examples
Table of Contents
This book is divided into three main parts, they are:
This section contains a gentle introduction to what PEAR_PackageFileManager is and has to offer. Included is general information about installing and using this PEAR package, and answers to frequently asked questions.
This section is intended to provide a quick introduction to get started understanding, installing, and running the bundle examples.
This section describes every API in the PEAR_PackageFileManager package. The description of each function may contain some or all of the following parts:
Synopsis
Shows the structure and prototype of the function.
Description
Gives a description about what the function does.
Parameter
Describes each parameter for the function along with the paramater types and names. Both required and optional parameters are listed.
Returns
Describes the returned value, if the function doesn't fail.
Throws
Describes the returned PEAR_Error objects, if the function
fails.
Note
Additional notes and information about the function. An example note would be if the function can be called statically.
See
Links to other related functions or manual entries.
Example
An example use of the function or class.
Table of Contents
Table of Contents
Basically PEAR_PackageFileManager takes an existing package.xml file and updates it with a new filelist and changelog.
This document is written as a guide to and reference for the PEAR_PackageFileManager package, for both beginner and expert users.
At the beggining, maintainers should wrote their package xml file by hand. PEAR_PackageFileManager (PFM) revolutionizes the maintenance of PEAR packages. With a few parameters, the entire package.xml is automatically updated with a listing of all files in a package.
Since first alpha release of PFM 1.6.0, this package can manage the new package.xml 2.0 format introduce with PEAR 1.4.0
The most significant change in PEAR 1.4 was addition of channels, a simple and effective method of distributing application development. PFM 1.6.0 help maintainers to build and manage the new package.xml 2.0 format that it is now simpler to distribute any PHP code project using the PEAR installer than it ever was.
2.1. General questions |
|
|
|
| 2.1.1. |
What does it cost ? |
|
You can download and use it for free. But don't delete the copyright notice. You can read terms of the license |
|
| 2.1.2. |
Do you offer support ? |
|
YES if there is no answer in this Guide and if you are ready to share some informations such as : your configuration (platform Win *nix mac, PHP version, PEAR packages installed) and perharps your script. |
|
| 2.1.3. |
I found a bug, what shall i do ? |
|
You can report it with the bug tracker at PEAR. |
|
| 2.1.4. |
What is PEAR ? |
|
PEAR (an acronym for PHP Extension and Application Repository) is a framework and distribution system for reusable PHP components. Don't forget to read also the PEAR Manual and PEAR FAQ. |
|
2.2. How to do |
|
|
|
| 2.2.1. |
I have a ... How to ? |
|
|
Table of Contents
Table of Contents
The package definition file package.xml is, as the name already implies, a
well-formed XML file that contains all information about a PEAR
package. Version 2.0 contains several important enhancements over
version 1.0, including
Channel support
Binary PECL packages support (not fully implemented in PEAR 1.4.0)
More specific dependency resolution
This chapter will describe the allowed elements of the package definition file.
The PEAR_PackageFileManager package simplifies the creation of package.xml. You can install PEAR_PackageFileManager via the usual command.
$ pear install PEAR_PackageFileManager
|
Note |
|---|---|
| Since version 1.6.0a1, PEAR_PackageFileManager supports package.xml 2.0 with the PEAR_PackageFileManager2 class. |
As any other xml file, the package definition file package.xml begin with a standard xml prolog.
The toplevel element in package.xml
is the element <package
version="2.0">.
The allowed sub elements are (bold entry is mandatory, while normal entry is optional):
<name>
The name of the package
<extends>
Each package with a major version x in x.y.z greater than 1 must superceed a previous package identify by the extends tag.
<channel>
| <uri>
Either use the channel tag that should contain the full channel name, not any alias, or use the uri tag that contain a Uniform Resource Identifier (URI) of your package.
<summary>
Short summary of the package's description
|
Warning |
|---|---|
| A one-line string longer than 25 characters will be truncated after 25th char. and ... will be appended to the string (to indicate a split). |
<description>
Any static long description. No size limitation.
|
Tip |
|---|---|
| This text should not change very much between releases, use instead the "notes" tag for release notes to identify what have changed since the previous version. |
<lead>,
<developer>,
<contributor>
and <helper>
These tags documente who develops a package, and who is still active.
<date>
The date when the current release has been rolled.
<time>
The time when the current release has been rolled. Default is current time if not specified.
<version>
Version tag documenting release version and API version.
<stability>
Stability tag documenting release stability and API stability.
<license>
License tag specifying software license and optional reference to license text.
<notes>
Notes tag specifying release changes introduced since previous version.
<contents>
Contents tag specifying the contents of a release.
<compatible>
compatible tag allow to work with recommended dependency and installed versions.
<dependencies>
dependencies tag specifying the dependencies of a release.
<usesrole>
Usesrole tag documenting custom file roles used in <contents>
<usestask>
Usestask tag documenting custom tasks used in <contents>
<phprelease>
| <extsrcrelease>
| <extbinrelease>
| <bundle>
These tags specifying the content type of a release.
<changelog>
Changelog-like information about the package.
Table of Contents
Table of Contents
Welcome to the PEAR_PackageFileManager tutorial, a self-paced guide that teaches you the basics of building your package with PEAR_PackageFileManager. This tutorial will familiarize you with the process of creating and updating package xml version 2.0
The tutorial is divided into 9 short lessons. In each lesson, you will learn how to create a new release, manage developers, files list, dependencies, perform complex installation tasks, and much more.
After you complete the tutorial, you can apply the skills you learn to your own packager copy.
Lesson 1, introducing PEAR_PackageFileManager compares automated and manual building methods.
Lesson 2, setting options defines types and values, and tells when and why you should use an option rather than an other.
Lesson 3, creating a new package teaches you how to build your first package from scratch.
Lesson 4, maintaining users list teaches you how to update the maintainers list. Add a new one, make one inactive, or definitively remove him.
Lesson 5, using tasks to customize file installation teaches you how to perform a custom installation with 3 basic tasks (replace, windowseol, unixeol) and 1 complex (postinstallscript).
Lesson 6, maintaining dependencies list teaches you how to update the dependencies list. Add a new one, remove one or just change its content.
Lesson 7, using custom file roles teaches you how to customize installation locations for each file rather than use standard categories (php, data, doc, test, script, src, ext).
Lesson 8, using custom file tasks teaches you how to customize installation with a third party task file, rather than using standard basic tasks: replace, eol, postinstall script.
Lesson 9, handling changelog teaches you how to read, remove, modify a changelog entry.
Table of Contents
This lesson :
describes the benefits of automated building
takes you on a short tour of the methods list
If you have ever created package xml manually, you are aware of its drawbacks. Manual building is time-consuming and tedious, giving sometime typo errors or xml grammar validation errors.
Automated building package.xml with
PEAR_PackageFileManager addresses these problems by dramatically
speeding up the building/validating process. You can create
package scripts that check all aspects of your application
distribution.
Describing a package xml version 1.0 or 2.0 requires four
mandatory properties (xml tag): name, channel (or
uri), summary, description, and one optional property:
extends.
Methods (setters) that should be called only once (at first package xml build-time), are listed below:
name
PEAR_PackageFile_v2::getPackage(),
PEAR_PackageFile_v2_rw::setPackage()
extends
PEAR_PackageFile_v2::getExtends(),
PEAR_PackageFile_v2_rw::setExtends()
channel
PEAR_PackageFile_v2::getChannel(),
PEAR_PackageFile_v2_rw::setChannel()
uri
PEAR_PackageFile_v2::getUri(),
PEAR_PackageFile_v2_rw::setUri()
summary
PEAR_PackageFile_v2::getSummary(),
PEAR_PackageFile_v2_rw::setSummary()
description
PEAR_PackageFile_v2::getDescription(),
PEAR_PackageFile_v2_rw::setDescription()
Table of Contents
This lesson :
describes exhaustive list of options to configure PEAR_PackageFileManager
Default behavior may be changed in many way. First one is to
define options with the setOptions() method. Here are the list of all
available options, with their default values:
Table 6.1. Reference of generation options for
package.xml 2.0
| Name | Type | Default |
|---|---|---|
| packagefile | string | package.xml |
| filelistgenerator | string | file |
| license | string | PHP License |
| baseinstalldir | string | null |
| changelogoldtonew | boolean | true |
| roles | array |
array(
'h' => 'src',
'c' => 'src',
'm4' => 'src',
'w32' => 'src',
'dll' => 'ext',
'php' => 'php',
'html' => 'doc',
'*' => 'data',
)
|
| dir_roles | array |
array(
'docs' => 'doc',
'examples' => 'doc',
'tests' => 'test',
)
|
| exceptions | array | array() |
| installexceptions | array | array() |
| ignore | array | array() |
| include | array | array() |
| notes | string | null |
| changelognotes | mixed (string | boolean) | false |
| outputdirectory | mixed (string | boolean) | false |
| pathtopackagefile | mixed (string | boolean) | false |
| lang | string | en |
| replacements | array | array() |
| globalreplacements | array | array() |
| globalreplaceexceptions | array | array() |
| simpleoutput | boolean | false |
| addhiddenfiles | boolean | false |
| cleardependencies | boolean | false |
| clearcontents | boolean | true |
| clearchangelog | boolean | false |
Table of Contents
This lesson :
teachs you how to build your first package from scratch.
teachs you to distinct usage of setOptions() and importOptions() methods.
While in reality, we could find the same generator script to
build a package.xml on first time,
and update it later, both classes PEAR_PackageFileManager and
PEAR_PackageFileManager2 provides two distinct ways of
generation, using : setOptions()
and importOptions(). We will
focus only, in this chapter, on the first method. Later we will
see usage of second method when we will talk how to update an
existing package.
Lets see step by step how to define a new package with the two versions of PEAR_PackageFileManager.
To define a new package we will need to know some informations, such as : its name, a little summary, and a longer description. But we need also to know where package sources resides, and where it should be installed (on PEAR infrastructure).
With package.xml version 1.0,
almost all properties were set with the setOptions() method. With package.xml version 2.0, there are new
functions to get/set property individually. Among these ones,
there is :
name
getPackage(), setPackage()
extends
getExtends(), setExtends()
channel
getChannel(), setChannel()
uri
getUri(), setUri()
summary
getSummary(), setSummary()
description
getDescription(),
setDescription()
To produce a package.xml version
1.0, here is the basic sheme
To produce a package.xml version
2.0
A new release, depends in part of package type, but as common properties, you should at least read/set :
date (optional, current date will be used)
getDate(), setDate()
time (optional, current time will be used; Only available
for package.xml 2.0)
getTime(), setTime()
version
getVersion(), setReleaseVersion(), setAPIVersion()
stability
getState(), getStability(), setReleaseStability(), setAPIStability()
license
getLicense(), setLicense()
notes
getNotes(), setNotes()
To produce a package.xml version
1.0
To produce a package.xml version
2.0
Even, if its not yet perfect, we have built our first
package.xml.
|
Important |
|---|---|
| A point in favor of PEAR_PackageFileManager2. It may generates package with PHP4 even if PHP5 tokens are detected in source code, while PEAR_PackageFileManager cannot. |
Defines where source files resides with option directive packagedirectory
Defines where source files should be installed (on PEAR infrastructure) with option directive baseinstalldir
Defines a name for your package, with a summary, and a long description.
Defines a release version number with a state under term of a license. API info are only available for package.xml 2.0, and package.xml 1.0 accept only a license name (without URI).
Defines at least one leader for the package maintainers list.
package.xml 2.0 dependencies
require at least definition of PHP and PEAR installer
minimum version to use, while dependencies are optional for
package.xml 1.0
Gets a fresh package files list depending of plugin used. See option directive filelistgenerator
Table 7.1. First package/release with package.xml 1.0 and package.xml 2.0
| 1.0 | 2.0 equivalent |
|---|---|
require_once 'PEAR/PackageFileManager.php';
PEAR::setErrorHandling(PEAR_ERROR_DIE);
$p1 = new PEAR_PackageFileManager();
|
require_once 'PEAR/PackageFileManager2.php';
PEAR::setErrorHandling(PEAR_ERROR_DIE);
$p2 = new PEAR_PackageFileManager2();
|
$p1->setOptions(array(
'packagedirectory' => 'C:\php\pear\MDB2',
'baseinstalldir' => '/'
));
|
$p2->setOptions(array(
'packagedirectory' => 'C:\php\pear\MDB2',
'baseinstalldir' => '/'
));
|
$name = 'MDB2';
$summary = 'database abstraction layer';
$description = 'PEAR MDB2 is a merge of the PEAR DB ...';
$p1->setOptions(array(
'package' => $name,
'summary' => $summary,
'description' => $description,
//...
));
|
$name = 'MDB2';
$summary = 'database abstraction layer';
$description = 'PEAR MDB2 is a merge of the PEAR DB ...';
$p2->setPackage($name);
$p2->setSummary($summary);
$p2->setDescription($description);
|
$release_notes = 'open TODO list ...';
$release_state = 'beta';
$release_version = '2.3.0';
$license = array(
'BSD License',
'http://www.opensource.org/licenses/bsd-license.php'
);
$p1->setOptions(array(
'state' => $release_state,
'version' => $release_version,
'notes' => $release_notes,
'license' => $license[0],
//...
));
|
$release_notes = 'open TODO list ...';
$release_state = 'beta';
$release_version = '2.3.0';
$api_state = 'stable';
$api_version = '2.0.0';
$license = array(
'BSD License',
'http://www.opensource.org/licenses/bsd-license.php'
);
$p2->setReleaseVersion($release_version);
$p2->setReleaseStability($release_state);
$p2->setAPIVersion($api_version);
$p2->setAPIStability($api_state);
$p2->setNotes($release_notes);
$p2->setLicense($license[0], $license[1]);
|
$p1->addMaintainer('lsmith', 'lead',
'Lukas Kahwe Smith', 'smith@pooteeweet.org');
|
$p2->addMaintainer('lead', 'lsmith',
'Lukas Kahwe Smith', 'smith@pooteeweet.org');
|
// No need to define PHP and PEAR dependency
|
$p2->setPhpDep('4.2.0');
$p2->setPearinstallerDep('1.4.3');
|
// No need to ask for file list contents generation
|
$p2->generateContents();
|
|
Warning |
|---|---|
Role and Handle parameter order of Maintainer are swapped
between package.xml version
1.0 and 2.0
|
Table of Contents
This lesson :
teachs you how to add a new user or remove him definitively
teachs you how to make a user inactive
teachs you how to change e-mail address, full name or role of a user
helps you get list of user (global, or by role)
No big change since API 1.5.x that manage package.xml 1.0; We use the same method name
addMaintainer() with parameters :
role
role of maintainer
Every maintainer has one of four possible roles:
handle
username on pear.php.net of maintainer
name
full name of maintainer
email
email address of maintainer
active
status of maintainer (active = 'yes', inactive = 'no')
|
Important |
|---|---|
No checking of duplicates is performed, use updateMaintainer() for that purpose.
|
|
Warning |
|---|---|
| Role, and Handle parameters are not given in same order. See example below: |
To produce a package.xml version
1.0
To produce a package.xml version
2.0
|
Tip |
|---|---|
|
You may now with PEAR_PackageFileManager 1.6.0+ add a new
user with a default inactive status. It was not possible
with package xml 1.0; When a user was added as maintainer,
it was considered as active. No way to made him inactive,
except to remove him definitively.
See previous example with "davidc", added as inactive. |
If you think this function is useless, you may consider that the package script generator could use data coming from another source (such as a database, a flat file, ...) rather than just hard-coded.
|
Important |
|---|---|
This feature is only available for PEAR_PackageFileManager
1.6.0 or better. To do the same thing, by programming, with
package.xml version 1.0, you
should set options with an empty "maintainers" array first,
before apply the addMaintainer() method.
|
To produce a package.xml version
1.0
To produce a package.xml version
2.0
Once again, if you think this function is useless, you may consider that the package script generator could use data coming from another source (such as a database, a flat file, ...) rather than just hard-coded.
Checking of duplicates is performed by usage of updateMaintainer(), and even allow adding a
new user if he did not exists.
|
Important |
|---|---|
This feature is only available for PEAR_PackageFileManager
1.6.0 or better. To do the same thing, by programming, with
package.xml version 1.0, you
should set options with an empty "maintainers" array first,
before apply the addMaintainer() method.
|
To produce a package.xml version
1.0
To produce a package.xml version
2.0
While API 1.5.x did not provides any way to retrieve user data of
a maintainer. PEAR_PackageFileManager 1.6.0+ allow to get a full
list organized by role or not, or a restricted list to a specific
role. These methods to get data are : getMaintainers(), getLeads(), getDevelopers(), getContributors() and getHelpers().
Here are the 5 methods in action :
With such functions, we can retrieve easily a specific user and change its properties. For example, suppose an helper become a new lead on the next stable release.
We could write something like :
Table of Contents
This lesson :
teachs you how to manipulate file content with 3 basic tasks
teachs you how to perform complex installation with a post install script
The replace task is nearly identical to the old <replace> tag from package.xml 1.0, and does a text search-and-replace of a file's contents.
In this example we will specialize file pear-phpdoc contents on installation, with the
most common and used basic task : <tasks:replace>.
Search all @PHP-BIN@
occurences in source file pear-phpdoc, and replace them by value of
option php_bin (PHP
CLI/CGI binary location).
To produce a package.xml version
1.0
To produce a package.xml version
2.0
|
Tip |
|---|---|
If all your files, or almost all of them as the same task
replacement to do, you can use the addGlobalReplacement() function that
accept same $type, $from, $to parameters (#2, #3, #4) of
addReplacement().
|
Windows and Unix platform handle end-of-line in a specific way that you should take care if you don't want to have surprise at run-time.
Windows convert line endings to \r\n, while Unix convert line endings to \n. You may decides to prevent problem at package-time, as well as at install-time, and adding two basic tasks : <tasks:windowseol>, and <tasks:unixeol>.
|
Note |
|---|---|
This feature is only available for package.xml, version 2.0
|
In this example we have two files pear-phpdoc and pear-phpdoc.bat that only one version should be
installed at run-time. We will see later how to specify this
condition.
If you want to do something else than just basic tasks (search and replace string, converting line ending), extreme customization is possible with <postinstallscript> tag. This tag define parameters that are used by PEAR installer to retrieve user input, while running a post-install script.
|
Note |
|---|---|
This feature is only available for package.xml, version 2.0
|
Distribution of full web application, including a database, is one of common problem that <tasks:postinstallscript> may solve.
In this example we will install a MySQL database with the
mysqlinstall script that resides
in server sub-directory of target
directory installation (see attribute baseinstalldir).
In package.xml, between <contents> tag we will find something like :
Generated by a script like this:
Adding a post install task <tasks:postinstallscript>
requires to build a PEAR_Task_Postinstallscript_rw instance for
the post install script ($task). This is made by PEAR_PackageFileManager::initPostinstallScript()
method.
Next we can add as much as we want any paramgroup id, such as :
<tasks:paramgroup><tasks:id>databaseSetup</tasks:id>.
This is made by PEAR_Task_Postinstallscript_rw::addParamGroup()
method.
Each paramgroup may have zero, one or more param. These params
are added by an array of PEAR_Task_Postinstallscript_rw::getParam(),
or false if there is no param.
Finally, post install script task is added to package xml by a
call to PEAR_PackageFileManager::addPostinstallTask()
method.
Post-install script files can be named anything one desires,
but the class within the file must be the same name as the
file with all path separators replaced by underscores, and a
fixed postfix "_postinstall". In other words, this
postinstall script: server/mysqlinstall.php, must contain a
class named server_mysqlinstall_postinstall.
API of a post install script always match, at least 2 functions :
init()
that initialize script environment with :
parameter #1 a reference to a PEAR_Config instance (current
configuration used for installation).
parameter #2 a reference to the current
PEAR_PackageFileManager
instance.
parameter #3 the last version of this package that was installed. This is a very important parameter, as it is the only way to determine whether a package is being installed from scratch, or upgraded from a previous version. Using this parameter, it is possible to determine what incremental changes, if any, need to be performed.
run()
is called at the conclusion of each parameter group in order to process the user's responses to queries. This method carry two parameters :
parameter #1 is an array that will contain a list of successfully completed parameter group sections. This can be used to restore any system changes made by the installation script.
parameter #2 identify the most recent paramgroup
or contains _undoOnError only triggered by
the PEAR installer on rollback process.
In our example, we should have a class pattern as this one :
This phase is important and allow script to communicate with a backend logger ($this->_ui), get information from your PEAR installation copy ($this->_config), get information on package release you are trying to install/upgrade ($this->_pkg) and the previous version installed (if any).
You may also add other data you think it's necessary to task proceed. For example a database existence indicator ($this->databaseExists), and what kind of driver we could use: either mysql or mysqli ($this->mysqliAvailable).
Deeper inside class server_mysqlinstall_postfix and
run() method, we find :
a way to commit action (each paramgroup id).
and another to revert action : _undoOnError
Explore in details one action (paramgroup id): databaseCreate specialized to creating new
database (default is peartest)
given by param name database of
this paramgroup.
|
Important |
|---|---|
In case of problem, don't forget to provide a way to
revert action already applied. PEAR installer will then
trigger _undoOnError phase
run.
|
Table of Contents
This lesson :
teachs you how to add a simple PHP and PEAR version dependency
teachs you how to add a package version dependency
teachs you how to add a php extension dependency
teachs you how to restrict installation on specifics Operating System and process architecture
PHP and PEAR installer dependencies are required in all package.xml with at least the minimum version property set.
PHP versioning requires at least the minimum version to install
this package.xml Its made by setPhpDep() method.
In table below, consider we have each time $p2 produced by code :
Table 10.1. setting PHP versions dependencies
| PHP code | XML equivalent |
|---|---|
$p2->setPhpDep('4.2.0');
|
<dependencies>
<required>
<php>
<min>4.2.0</min>
</php>
</required>
</dependencies>
|
$p2->setPhpDep('4.2.0', '5.0.0');
|
<dependencies>
<required>
<php>
<min>4.2.0</min>
<max>5.0.0</max>
</php>
</required>
</dependencies>
|
$p2->setPhpDep('4.2.0', '5.0.0', array('5.0.0'));
|
<dependencies>
<required>
<php>
<min>4.2.0</min>
<max>5.0.0</max>
<exclude>5.0.0</exclude>
</php>
</required>
</dependencies>
|
$p2->setPhpDep('4.2.0', '5.1.0', array('5.0.0', '5.0.1'));
|
<dependencies>
<required>
<php>
<min>4.2.0</min>
<max>5.1.0</max>
<exclude>5.0.0</exclude>
<exclude>5.0.1</exclude>
</php>
</required>
</dependencies>
|
PEAR installer versioning requires at least the minimum version
of PEAR that can properly parse and install the package.xml
containing it. Its made by setPearinstallerDep() method.
In table below, consider we have each time $p2 produced by code :
Table 10.2. setting PEAR installer dependencies
| PHP code | XML equivalent |
|---|---|
$p2->setPearinstallerDep('1.4.3');
|
<dependencies>
<required>
<pearinstaller>
<min>1.4.3</min>
</pearinstaller>
</required>
</dependencies>
|
$p2->setPearinstallerDep('1.4.3', '1.4.11');
|
<dependencies>
<required>
<pearinstaller>
<min>1.4.3</min>
<max>1.4.11</max>
</pearinstaller>
</required>
</dependencies>
|
$p2->setPearinstallerDep('1.4.0', false, '1.4.3');
|
<dependencies>
<required>
<pearinstaller>
<min>1.4.0</min>
<recommended>1.4.3</recommended>
</pearinstaller>
</required>
</dependencies>
|
$p2->setPearinstallerDep('1.4.0', false, false,
array('1.4.1', '1.4.2'));
|
<dependencies>
<required>
<pearinstaller>
<min>1.4.0</min>
<exclude>1.4.1</exclude>
<exclude>1.4.2</exclude>
</pearinstaller>
</required>
</dependencies>
|
PEAR 1.4.0 and package.xml 2.0
supports more package dependencies than package.xml 1.0, but we will see in details
what are differences and how we can do (try to do) the same job.
In table below, consider we have each time $p1 produced by code :
Table 10.3. package.xml 1.0 dependencies
| PHP code | XML equivalent |
|---|---|
// 'has' relation
$p1->addDependency('PEAR',
false, 'has', 'pkg', false);
|
<deps>
<dep type="pkg" rel="has"
optional="no">
PEAR
</dep>
</deps>
|
// 'greater or equal' relation
$p1->addDependency('Archive_Tar',
'1.0.0', 'ge', 'pkg', false);
|
<deps>
<dep type="pkg"
rel="ge" version="1.0.0"
optional="no">
Archive_Tar
</dep>
</deps>
|
// 'greater than' relation
$p1->addDependency('MDB2',
'2.1.0', 'gt', 'pkg', true);
|
<deps>
<dep type="pkg"
rel="gt" version="2.1.0"
optional="yes">
MDB2
</dep>
</deps>
|
// 'less or equal' relation
$p1->addDependency('Console_Getopt',
'1.2', 'le', 'pkg');
|
<deps>
<dep type="pkg"
rel="le" version="1.2"
optional="no">
Console_Getopt
</dep>
</deps>
|
// 'less than' relation
$p1->addDependency('Text_Highlighter',
'0.7.0', 'lt', 'pkg', true);
|
<deps>
<dep type="pkg"
rel="lt" version="0.7.0"
optional="yes">
Text_Highlighter
</dep>
</deps>
|
// 'between' relation
$p1->addDependency('PEAR_PackageFileManager',
'1.6.0a1', 'ge');
$p1->addDependency('PEAR_PackageFileManager',
'1.6.0b5', 'le');
|
<deps>
<dep type="pkg"
rel="ge" version="1.6.0a1"
optional="no">
PEAR_PackageFileManager
</dep>
<dep type="pkg"
rel="le" version="1.6.0b5"
optional="no">
PEAR_PackageFileManager
</dep>
</deps>
|
// 'conflicting' dependency
$p1->addDependency('DB',
false, 'not', 'pkg');
|
<deps>
<dep type="pkg" rel="not">DB</dep>
</deps>
|
In table below, consider we have each time $p2 produced by code :
Table 10.4. package.xml 2.0 dependencies
| PHP code | XML equivalent |
|---|---|
// 'has' relation
$p2->addPackageDepWithChannel('required',
'PEAR', 'pear.php.net');
|
<dependencies>
<required>
<!-- ... -->
<package>
<name>PEAR</name>
<channel>pear.php.net</channel>
</package>
</required>
</dependencies>
|
// 'greater or equal' relation
$p2->addPackageDepWithChannel('required',
'Archive_Tar', 'pear.php.net',
'1.0.0');
|
<dependencies>
<required>
<!-- ... -->
<package>
<name>Archive_Tar</name>
<channel>pear.php.net</channel>
<min>1.0.0</min>
</package>
</required>
</dependencies>
|
// 'greater than' relation
$p2->addPackageDepWithChannel('optional',
'MDB2', 'pear.php.net',
'2.1.0', false, false, '2.1.0');
|
<dependencies>
<required>
<!-- ... -->
</required>
<optional>
<package>
<name>MDB2</name>
<channel>pear.php.net</channel>
<min>2.1.0</min>
<exclude>2.1.0</exclude>
</package>
</optional>
</dependencies>
|
// 'less or equal' relation
$p2->addPackageDepWithChannel('required',
'Console_Getopt', 'pear.php.net',
false, '1.3.0');
|
<dependencies>
<required>
<!-- ... -->
<package>
<name>Console_Getopt</name>
<channel>pear.php.net</channel>
<max>1.3.0</max>
</package>
</required>
</dependencies>
|
// 'less than' relation
$p2->addPackageDepWithChannel('optional',
'Text_Highlighter', 'pear.php.net',
false, '0.7.0', false, '0.7.0');
|
<dependencies>
<required>
<!-- ... -->
</required>
<optional>
<package>
<name>Text_Highlighter</name>
<channel>pear.php.net</channel>
<max>0.7.0</min>
<exclude>0.7.0</exclude>
</package>
</optional>
</dependencies>
|
// 'between' relation
$p2->addPackageDepWithChannel('required',
'PEAR_PackageFileManager', 'pear.php.net',
'1.6.0a1', '1.6.0b5');
|
<dependencies>
<required>
<!-- ... -->
<package>
<name>PEAR_PackageFileManager</name>
<channel>pear.php.net</channel>
<min>1.6.0a1</min>
<max>1.6.0b5</max>
</package>
</required>
</dependencies>
|
// 'conflicting' dependency
$p2->addConflictingPackageDepWithChannel('DB',
'pear.php.net');
|
<dependencies>
<required>
<!-- ... -->
<package>
<name>DB</name>
<channel>pear.php.net</channel>
<conflicts/>
</package>
</required>
</dependencies>
|
When you use uri-based package dependencies rather than
channel-based package dependencies (see previously), you have
to use: addPackageDepWithUri()
method instead of addPackageDepWithChannel().
Here is a simple example to produce:
you should write:
|
Important |
|---|---|
Do not append tgz or
tar extension, when you
give the uri. PEAR installer will try to fetch
http://www.example.com/Foo-1.3.0.tgz or
http://www.example.com/Foo-1.3.0.tar
|
|
Note |
|---|---|
List of package installed through pseudo channel __uri
may be displayed, on command line, with :
pear list -a
|
As with all dependencies that support versioning, all standard versioning tags are supported (min, max, recommended, exclude). In addition, the <conflicts> tag is supported to create a negative dependency.
Table 10.5. php extension dependencies version 1.0
| PHP code | XML equivalent |
|---|---|
// 'has' relation
$p1->addDependency('gettext', false, 'has', 'ext');
|
<deps>
<dep type="ext" rel="has"
optional="no">
gettext
</dep>
</deps>
|
|
Caution |
|---|---|
| Do not use comparaison operator with version, on php extension dependency, it won't work as you would expected. |
Table 10.6. php extension dependencies version 2.0
| PHP code | XML equivalent |
|---|---|
// 'has' relation
$p2->addExtensionDep('required', 'gettext');
|
<dependencies>
<required>
<!-- ... -->
<extension>
<name>gettext</name>
</extension>
</required>
</dependencies>
|
// 'greater or equal' relation
$p2->addExtensionDep('optional', 'gd', '2.0.0');
|
<dependencies>
<optional>
<!-- ... -->
<extension>
<name>gd</name>
<min>2.0.0</min>
</extension>
</optional>
</dependencies>
|
Dealing with OS dependency to restrict a
package installation is made with call to addOsDep() method.
For example, if we want to restrict a package installation on linux OS, or on every OS except windows, we should write :
Table 10.7. OS installation condition
| PHP code | XML equivalent |
|---|---|
$p2->addOsDep('linux');
|
<dependencies>
<required>
<!-- ... -->
<os>
<name>linux</name>
</os>
</required>
</dependencies>
|
$p2->addOsDep('windows', true);
|
<dependencies>
<required>
<!-- ... -->
<os>
<name>windows</name>
<conflicts />
</os>
</required>
</dependencies>
|
Dealing with Architecture dependency to
restrict a package installation to a specific OS and processor
architecture is made with call to addArchDep() method.
For example, if we want to restrict a package installation on linux OS, and intel 8086 family processor, or on every architecture except Mac OS X (darwin), we should write :
Table 10.8. Arch installation condition
| PHP code | XML equivalent |
|---|---|
$p2->addArchDep('linux-*-i?86-*');
|
<dependencies>
<required>
<!-- ... -->
<arch>
<pattern>linux-*-i?86-*</pattern>
</arch>
</required>
</dependencies>
|
$p2->addArchDep('darwin', true);
|
<dependencies>
<required>
<!-- ... -->
<arch>
<pattern>darwin</pattern>
<conflicts />
</arch>
</required>
</dependencies>
|
Table of Contents
This lesson :
teachs you how to add a new extension role mapping to default role influences array.
teachs you how to improve message when dealing with package role handler not installed on your system.
Default role mapping array separates extension into seven categories.
Table 11.1. extension role mapping reference
| Role | Extension |
|---|---|
| php | php |
| data | all other extension |
| doc | html |
| test | none |
| script | none |
| src | h, c, m4, w32 |
| ext | dll |
Once a package that reference, manage, the new role is properly installed in your system, you can use it, and add it to the default role mapping array.
We suppose to have previously installed a package that manage the
new role web. Here we will
assume that all log files (*.log) will be copied into directory
declared by <locationconfig> tag of xml web file role (see PEAR/Installer/Role/Web.xml).
However, if a user does not have the package installed that provides the custom role web, then the error message on installation will simply say File ... has invalid role "web" should be one of data, doc, php, script, test which is not very helpful.
If you don't want to give the same behavior to all file with same extension, but only to one or a set of them, then use option directive exceptions.
This problem may be solve easily by adding a <usersrole>
tag documenting package to install that will handle the new role.
Uses methods : addUsesrole() with
(replace role) or without (append role) its resetUsesrole() companion.
Table 11.2. install custom file role handler
| PHP code | XML equivalent |
|---|---|
$p2->resetUsesrole();
// use channel-based package
$p2->addUsesrole('web', 'Role_Web', 'pearified.com');
|
<usesrole>
<role>web</role>
<package>Role_Web</package>
<channel>pearified.com</channel>
</usesrole>
|
$p2->resetUsesrole();
// use uri-based package
$p2->addUsesrole('web',
'http://pearified.com/Role-1.1.1');
|
<usesrole>
<role>web</role>
<uri>http://pearified.com/Role-1.1.1</uri>
</usesrole>
|
|
Tip |
|---|---|
| If Role_Web package is not installed, then PEAR installer take aware user with a message like This package contains role "web" and requires package "channel://pearified.com/Role_Web" to be used. |
Table of Contents
This lesson :
teachs you how to add a new task file provide by a third party to default tasks array.
teachs you how to improve message when dealing with package task handler not installed on your system.
Standard file tasks provided by default, allow to : search-and-replace string into file contents, change line-ending, and add a complex postinstall script.
If you want to specialize your installation with a complex task, you will need first to learn how to create customized task in PHP .
Once a package that reference, manage, the new task file is
properly installed in your system (into directory PEAR/Task/), you can use it with a call to
addTaskToFile().
We suppose to have previously installed a package that manage the new task stripwhitespace.
|
Note |
|---|---|
Install the PEAR_Task_Stripwhitespace package version 0.1.0
on __URI channel.
pear install http://pear.laurent-laville.org/get/PEAR_Task_Stripwhitespace-0.1.0.tgz
|
This script will generate something like :
|
Important |
|---|---|
Allways generate file list contents with generateContents() before trying to add
a task to one of file with addTaskToFile().
|
However, if a user does not have the package installed that provides the custom task stripwhitespace, then the error message on installation will simply say Unknown task "stripwhitespace" which is not very helpful.
This problem may be solve easily by adding a <userstask>
tag documenting package to install that will handle the new task.
Uses methods : addUsestask() with
(replace task) or without (append task) its resetUsestask() companion.
Table 12.1. install custom file task handler
| PHP code | XML equivalent |
|---|---|
$p2->resetUsestask();
// use channel-based package
$p2->addUsestask('foo',
'Task_Foo', 'pear.example.com');
|
<usestask>
<task>foo</task>
<package>Task_Foo</package>
<channel>pear.example.com</channel>
</usestask>
|
$p2->resetUsestask();
// use uri-based package
$p2->addUsestask('foo',
'http://pear.example.com/Task_Foo-0.1.0');
|
<usestask>
<task>foo</task>
<package>Task_Foo</package>
<uri>http://pear.example.com/Task_Foo-0.1.0</uri>
</usestask>
|
|
Tip |
|---|---|
| If Task_Foo package is not installed, then PEAR installer take aware user with a message like This package contains task "foo" and requires package "http://pear.example.com/Task_Foo-0.1.0.tgz" to be used. |
Table of Contents
This lesson :
teachs you how to read full changelog history.
teachs you how to remove definitively full changelog section from package.xml
If you want to retrieve information from an old version, or just
count releases, you have only to use one method: getChangelog().
We will create a RSS newsfeed with result of getChangelog() assisted by PEAR package
XML_Serializer .
|
Note |
|---|---|
| Original article create a RSS newsfeed is locate at http://freedomink.org/node/62 |
Example 13.1. create a RSS newsfeed
If you don't want to keep history of changes when you generate a
new release, then you have only to set option clearchangelog to true.
|
Warning |
|---|---|
| This option is only available since stable release 1.6.0 |
Table of Contents
<channel> - What is a channel?
Channels are new in PEAR 1.4.0. Channels are a systemized way of differentiating between different download sources. One such download source is pear.php.net, another is pecl.php.net, and there are several third party channels slowly springing up around the net.
The <channel> tag should contain the full channel name, not any alias (don't use "pear", use "pear.php.net".
A good rule of thumb to use when determining what channel name to use is "where do I upload my releases to?" If the answer is pear.php.net, that is your package's channel. If the answer is pecl.php.net, then that is your channel.
If you aren't running a channel server and wish to serve your packages as well as allow other packages to remotely depend on your package, the new uri-based package distribution method is the best choice, see the <uri> tag documentation link below.
<uri> - When should I use <uri>?
If you do not have a channel server and wish to serve your packages so that others can depend on them, use <uri>. This should contain a static uri that links to a single package version's downloadable .tgz
If you do not need to allow external remote dependencies, then simply use the pear.php.net channel as your package's channel.
For instance, if you wish to serve package Foo version 1.1.0 from www.example.com, use the uri "http://www.example.com/Foo-1.1.0". Note that the uri must contain the full path MINUS THE EXTENSION. Provide both Foo-1.1.0.tgz and Foo-1.1.0.tar for users without gzip.
<lead>, <developer>, <contributor>, and <helper> - Developer documentation for a release
In package.xml 1.0, a developer was documented using the <maintainer> tag inside of a redundant <maintainers> container tag. This has been simplified in package.xml 2.0 both to slightly speed parsing and to make validation of the xml simpler. Now, the contents of the <role> tag has been extracted as 4 tags to describe the maintainers of a package.
In addition, a new internal tag <active> has been added, so that you can honor retired developers' work without having to remove them altogether from package.xml.
|
Warning |
|---|---|
| Tag order is important. List leads followed by developers followed by contributors and finally helpers. |
<version> - versioning in package.xml 2.0
In package.xml 1.0, the version was simply the version. package.xml 2.0 splits the concept of versioning into two components, release and api.
The release version is the same familiar versioning concept from package.xml 1.0. This version is validated very carefully by the packager.
The API version is informational only - the installer does not
use it. It can be used for a package-time replacement by the
installer. This can be very useful when implementing a reflective
method such as getApiVersion. In
addition, the API version is very loosely validated, and only
requires a version_compare()-compatible version number.
<stability> - specifying release and API stability
In package.xml 1.0, stability was known as "state" which is not the most accurate description. package.xml 2.0 introduces the term stability and like version splits the concept of stability into two components, release and api.
The release stability is the same familiar state from package.xml 1.0. It can be one of:
snapshot - a frozen picture of development at a particular moment
devel - a very new non-production release. Devel should be used for extremely new, practically untested code.
alpha - a new non-production release. Alpha should be used for new code that has an unstable API or untested code.
beta - a non-production release. Beta should be used for code that has a stable API and is nearing a fully stable release. Regresion tests and documentation should exist or soon follow to qualify as a beta release. Release candidates should use the beta stability.
stable - a production release. Stable releases must have a stable API, and must have regression tests and documentation.
The API stability is informational only - the installer does not use it.
<license> - specifying software license and optional reference to license text
In package.xml 1.0, the license tag only contained the name of the license. In package.xml 2.0, there are two optional attributes, "uri" and "filesource". "uri" contains a uri that identifies the text of a license, such as "http://www.php.net/license" for the PHP License. "filesource" can be used to specify a LICENSE file within an actual package that contains the text of the license.
<contents> - specifying the contents of a release
In package.xml 1.0, the contents tag was <filelist>. The purpose of the tag changed dramatically in package.xml 2.0, warranting a name change. Now, <filelist> can be found in the release section of the package.xml.
<contents> is used to describe the contents of a tarball. Nothing further. All files in the contents tag will be placed into the tarball regardless of whether they eventually get installed by the PEAR installer. This fact can be used to create a very versatile tarball, one that can be directly unzipped and work out of the box as well as be installed by the PEAR installer and work out of the box.
For most release types, contents contains a single <dir> tag that then either contains nested dir tags and/or <file> tags.
<dir> - documenting a directory in the <contents> tag
The <dir> tag is identical to package.xml 1.0. Required attributes are name and optional attributes are baseinstalldir (the relative location where all files and subdirectories will be installed)
Note that all files must be contained in a single top-level <dir> tag. For simple packages, simply use <dir name="/"> as the directory name
<file> - documenting a file in the <contents> tag
The <file> tag is almost identical to package.xml 1.0. Required attributes are name and role. Optional attributes are baseinstalldir and md5sum. Optional attributes platform and install-as have been replaced by the release tags. Specifically, <install> is used to specify install-as, and the <ignore> tag can be used in conjunction with <installconditions> to exclude packages from being installed on particular platforms.
For those familiar with the platform attribute, the way to handle this example:
<file name="scripts/foo.bat" role="script" install-as="foo.bat" platform="windows">
is to in fact create two release sections. The file tag would then look like:
<file name="scripts/foo.bat" role="script">
and the release section would look like this:
<phprelease> <installconditions> <os>windows</os> </installconditions> <install name="scripts/foo.bat" as="foo.bat"/> </phprelease> <phprelease> <ignore name="scripts/foo.bat"/> </phprelease>
Note that the second <phprelease> tag could just as easily have had an <installconditions> tag containing <os>unix</os>, but this is unnecessary, as the second release will be processed on any system that is not a windows system.
tasks for <file>s - specialized file installation and manipulation
Tasks provide a flexible and customizable way to manipulate file contents or to perform complex installation tasks (hence the name "tasks"). By default, PEAR comes with 4 tasks, but customized tasks can be added simply by adding a file into the PEAR/Tasks directory that follows the conventions of existing tasks. This page does not describe how to create a custom task, only how to use them in package.xml.
There are 3 basic tasks and 1 complex task distributed with PEAR. The basic tasks are "tasks:replace", "tasks:windowseol", and "tasks:unixeol". The complex task is "tasks:postinstallscript". "tasks:replace" is nearly identical to the old <replace> tag from package.xml 1.0, and does a text search-and-replace of a file's contents. "tasks:windowseol" and "tasks:unixeol" manipulate the line endings of a file to ensure that the correct line endings are in place for critical files like DOS .bat batch files and unix shell scripts. "tasks:postinstallscript" allows users to choose to run a script to perform further installation functions.
The replace task has 3 required attributes:
type - This must be either package-info or pear-config. package-info replacements extract information from package.xml itself to use as the replacement text. pear-config replacements use the value of a configuration variable (as displayed by
pear config-show
) as the text for replacement.
from - Text to search for in a file. Traditionally, this text is enclosed in "@" to differentiate it from normal text, as in from="@version@"
to - Abstract item to use as a replacement for all occurences of "from". package-info replacements can be one of version, release_date, release_state, release_license, release_notes, apiversion, name, summary, description, notes, time, date, and for some packages extends, srcpackage, srcuri, and providesextension.
Note that package-info replacements are performed at packaging time, so files contain package-info replacements inside a .tgz/.tar release. pear-config replacements can only occur on the installation system, and are performed at install-time.
This task can be used to enable packaging of windows-specific files (like DOS batch files) on a non-windows system, such as unix systems that convert line endings to \n. Note that this task is performed at package-time, as well as at install-time, so files will contain the correct line endings inside a .tgz/.tar release.
This task can be used to enable packaging of unix-specific files (like sh shell scripts) on a non-unix system, such as windows systems that convert line endings to \r\n. Note that this task is performed at package-time, as well as at install-time, so files will contain the correct line endings inside a .tgz/.tar release.
The postinstallscript task informs the installer that the file it references is a post-installation script.
For security reasons, post-install scripts must be manually executed by the users, and as such the installer has special code that is separate from other tasks.
The <postinstallscript> tag may define parameters that are used by the installer to retrieve user input. In order to support both the web installer and the command-line installer, all processing of input is performed by PEAR and passed to the post-install script in a strict format. All you need to do is define the parameters using xml inside the <postinstallscript> tag.
Here is the xml representing a simple post-install script with parameters:
Note that the only type recognized at this stage is "string" but others will follow. A more complex example follows:
This post-installation script has two parameter groups. The first parameter group has special instructions that are displayed to the user to assist in answering the required prompts. After the first group is processed, the second group is processed (naturally). However, in this case, the second group is a conditional parameter group. A conditional parameter group examines the user input from previous parameter groups and only displays its parameter prompts if a single parameter fits a test. The condition is defined by three tags, <tasks:name>, <tasks:conditiontype>, and <tasks:value>. Note that all three tags are required or xml validation will fail.
<tasks:name> is the parameter name from a previous parameter group. The format of name is groupID::parameterName, so as you see above, "first::test" refers to the <tasks:param> test from the <tasks:paramgroup> first.
<tasks:conditiontype> determines how the parameter input function will process the value of the parameter specified in <tasks:name>, and can be one of three values, "=" "!=" or "preg_match".
=: This (obviously) tests whether the parameters value is equal to the <tasks:value> tag
!=: This (obviously) tests whether the parameters value is not equal to the <tasks:value> tag
preg_match: This uses the content of the
<tasks:value> tag as if it were the stuff between /
and / in a preg_match function call. Do NOT
include // brackets in the regular expression. In the
<tasks:paramgroup> second, the value "g+" will
become:
<compatible> - Alleviating strict versioning with <compatible>
The <compatible> tag is designed to be used with a <package> dependency that contains a <recommended> version tag from package pear.example.com/Bar version 1.3.0 like so:
The above dependency can be translated into English as follows: "Use the package pear.example.com/Foo, but only versions 1.0.0 or newer. If pear.example.com/Foo is not installed, install version 1.5.2. If pear.example.com/Foo is installed and is not version 1.5.2, fail unless --force is specified, or pear.example.com/Foo is compatible with me."
That last clause "...or pear.example.com/Foo is compatible with me." is controlled by the <compatible> tag. If package Foo version 1.5.3's package.xml has a <compatible> like so:
This will instruct the installer that pear.example.com/Foo version 1.5.3 is compatible with pear.example.com/Bar versions 1.2.0 to 1.3.0 inclusive, but is not compatible with 1.2.9.
It is very important to note that only existing versions that have been tested with the package should be mentioned in the <compatible> tag. Future versions of pear.example.com/Bar should simply upgrade the <recommended> tag.
<compatible> may contain three versioning tags. The required <min> and <max> are used to define the range of tested and compatible versions, and <exclude> is used to exclude any versions within the range. In the example above, 1.3.0 and 1.2.0 are the highest and lowest versions that may be excluded. There can be an unlimited number of <compatible> tags inside a package.xml.
<dependencies> - Dependency Specification in package.xml 2.0
Dependencies are the most difficult aspect of programming. Using code written by other people can be a nightmare without simple ways to control bugs and API changes. Arguably, the handling of dependencies is PEAR's greatest strength, although there are many other nice features. Regardless of your personal opinion of the importance of dependencies, it is crucial to understand how to specify a dependency, and the different ways to ensure that your package is only used on systems that support it.
In package.xml 1.0, dependencies were relatively simple, but at the cost of usefulness. Specifying a dependency on a package for applications was actually dangerous. If you wished to limit an installed version of a package to a single version, it would mean preventing upgrade at any cost. package.xml 2.0 provides a simple way to enforce stricter dependency versioning without making upgrades onerous.
In package.xml 1.0, dependencies on PHP extensions like PECL extensions was near to a disaster. Extensions had to be present in the php.ini and loaded in memory in order to validate as being installed. This is often impossible, as a different php.ini is used for a production website versus the php.ini used for the pear installer. With package.xml 2.0, dependencies on a PECL-like extension is simple and straightforward, and only requires that the package be installed, and not that the extension be present in memory, although an older style extension dependency is also supported.
package.xml 1.0 supports two kinds of dependencies, required and optional. package.xml 2.0 also supports these two dependency types, but introduces a new kind of dependency concept: an optional dependency group. Dependency groups define a feature set. Instead of thinking "This package optionally depends on Net_FTP and optionally depends on Log" think "To remotely install packages, I need the remoteinstall feature, which needs Net_FTP and the Log package". This grouping allows defining sets of packages and extensions that comprise a feature and must be installed all at once for the feature to function properly.
package.xml 1.0 only supported php, package, and extension dependencies. package.xml 2.0 supports dependencies on php, package, extension, os, architecture, and PEAR installer. In addition, package.xml 2.0 supports depending on a static package located at a url, and depending on a package that provides an extension to PHP like PECL packages.
The PEAR installer dependency is not a dependency on the PEAR package, but a dependency on the currently running PEAR installer, and is more similar to a PHP dependency in that it requires the specified version to be running in memory. This is very useful for circumventing difficult bugs in the PEAR installer that render a package install useless.
The <dependencies> tag re-organizes dependencies into groups and "extracts" attributes into tags. It also un-abbreviates words for clarity and human-readability. The following excerpt of a package.xml version 1.0:
Approximately translates into this format in package.xml 2.0:
These changes were made to simplify xml validation and parsing. Note that unlike package.xml 1.0, the <pearinstaller> and <php> dependencies are required in all package.xml. In addition the <min> tag is required in both <pearinstaller> and <php> dependencies.
The <pearinstaller> dependency defines the minimum version of PEAR that can properly parse and install the package.xml containing it. As with all dependency tags that support versioning, these 4 tags are supported to define versioning:
<min> - minimum version of PEAR required to install this package.xml. This tag is required in all package.xml <pearinstaller> dependencies.
<max> - maximum version of PEAR installer supported. Use with caution! This tag will prevent the package from being installed by anyone with a newer version of PEAR!
<recommended> - recommended version of PEAR installer. This tag is used for strict version control. The installer will refuse to install a package without the --force option unless the version exactly matches recommended. This can be used to provide a level of extra security, as a package can be set to install using a version that is known to work without limiting future upgrades.
<exclude> - incompatible versions of PEAR installer. Use this to prevent the package from being installed by any PEAR version that cannot properly install the package. Multiple <exclude> tags may be used to exclude more than one version.
As with all dependency tags that support versioning, these 3 tags are supported to define versioning:
<min> - minimum version of PHP required to install this package.xml. This tag is required in all package.xml <php> dependencies.
<max> - maximum version of PHP supported.
<exclude> - incompatible versions of PHP. Use this to prevent the package from being installed by any PHP version that cannot properly work with the package. Multiple <exclude> tags may be used to exclude more than one version.
Subpackage dependencies share the same xml format as package dependencies. The subpackage dependency should only be used if a package is split into more than one package. In other words, if the child package contains the same files as any earlier version of the parent package, the child package would normally conflict with the parent package because it would be attempting to overwrite the parent package's files with its own files.
A simple example should make this clear. Package Foo 1.0.0 contains Foo.php and Foo/Bar.php. Package Foo's developers decide to split Foo into two packages: Foo and Foo_Bar. Foo 1.1.0 contains foo.php, and Foo_Bar 0.1.0 contains Foo/Bar.php. Foo_Bar 0.1.0 conflicts directly with Foo 1.0.0, as both contain the file Foo/Bar.php.
If Foo has a subpackage dependency on Foo_Bar, then the installer will ignore the conflict between Foo 1.0.0's Foo/Bar.php and Foo_Bar 0.1.0's Foo/Bar.php just as it ignores the conflict between Foo 1.0.0's Foo.php and Foo 1.1.0's Foo.php.
Understandably, the <package> dependency is PEAR's most complex dependency. PEAR 1.4.0 supports 3 different kinds of package dependencies:
Normal, traditional channel server-based package dependencies (same idea as package.xml 1.0).
Dependencies on packages that provide PHP extensions (like PECL packages). (These can be both server-based and uri-based dependencies)
Static, non-traditional uri-based package dependencies.
The most common kind of package dependency is a channel-based dependency. This dependency from package.xml version 1.0:
translates to this dependency in package.xml version 2.0:
Note that <channel> is a required tag for all typical package dependencies. Use pear.php.net for all packages that were packaged using package.xml 1.0, regardless of where they are downloaded from.
As with all dependency tags that support versioning, all standard versioning tags are supported (min, max, recommended, exclude). In addition, the <conflicts> tag is supported to create a negative dependency.
<min> - minimum version of a dependency. If the dependency package is installed, and is older than this version, installation will fail.
<max> - maximum version of a dependency. If the dependency package is installed, and is newer than this version, installation will fail.
<recommended> - recommended version of a dependency. This tag is used for strict version control. The installer will refuse to install a package without the --force option unless the version exactly matches recommended. This can be used to provide a level of extra security, as a package can be set to install using a version that is known to work without limiting future upgrades.
Note that use of the <compatible> tag in the dependency's package.xml can be used to circumvent the installer's strictness. In essence, the <compatible> tag tells the installer that a dependent package is compatible with the current package, even though it is not the recommended version.
<exclude> - incompatible versions of a package. Multiple <exclude> tags may be used to exclude more than one version of a dependency.
<conflicts> - Negates the dependency. If the package is installed, it cannot satisfy the requirements of the dependency or installation will fail.
Here is a rough chart describing how to convert from package.xml 1.0 "rel" attributes to a package.xml 2.0 equivalent.
Table 14. Converting package.xml 1.0 package dependencies to package.xml 2.0
| 1.0 | 2.0 equivalent |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Let's look at uri-based package dependencies. Here is a simple example:
This dependency tells the installer to fetch http://www.example.com/Foo-1.3.0.tgz or http://www.example.com/Foo-1.3.0.tar (both must be available!) if the package Foo is not installed. All uri packages must contain a <uri> tag rather than a <channel> tag and will automatically belong to the pseudo-channel "__uri", but that is not important to the discussion of how to format the xml to create the uri-based package dependency.
uri-based package dependencies cannot contain any versioning information, as this is irrelevant: there is only one version possible with a static uri. uri-based dependencies can contain the <conflicts/> tag to specify an absolute conflict with the package, and the <providesextension> tag to specify an extension provided by the static package.
package.xml 2.0 supports differentiating release types, and as such also supports dependencies on PECL-style packages that use the extbinrelease or extsrcrelease type.
To specify a dependency on a PHP extension that can be distributed as a PECL package, but could also be bundled with PHP by default, such as the PDO extension, use this dependency style:
The magic is in the <providesextension> tag. This tag tells the installer to take this process when validating the dependency:
Is the extension "PDO" present in memory? If so, is it version 0.3.1 or higher?
If not, is the user also installing pecl.php.net/PDO at the same time as this package? If so, is it version 0.3.1 or higher?
If not, is pecl.php.net/PDO installed, and is the version 0.3.1 or higher?
If any of the three conditions above validate in the order specified, the dependency will be satisfied and installation will continue. This system allows users to use a different php.ini to install PHP extensions and also provides a fail-safe system to depend on extensions.
|
Warning |
|---|---|
|
<providesextension>, like all other extension-related functions in PHP, is case-sensitive. Do not use "pdo" for the "PDO" extension, or your dependency will always fail. |
As with all dependency tags that support versioning, all standard versioning tags are supported (min, max, recommended, exclude). In addition, the <conflicts> tag is supported to create a negative dependency.
<min> - minimum version of PHP extension to install this package.xml.
<max> - maximum version of PHP extension supported.
<recommended> - recommended version of PHP extension. This tag is used for strict version control. The installer will refuse to install a package without the --force option unless the version exactly matches recommended. This can be used to provide a level of extra security, as a package can be set to install using a version that is known to work without limiting future upgrades.
<exclude> - incompatible versions of PHP extension. Multiple <exclude> tags may be used to exclude more than one version.
<conflicts> - Negates the dependency. If the extension is present, it cannot satisfy the requirements of the dependency or installation will fail.
The OS dependency is used to restrict a package to both a particular class of OSes (like unix) and to a specific OS (like darwin, or freebsd). Here is an example:
To specify that a package can be installed on every OS except the one specified, use the <conflicts/> tag:
Possible OS values are:
In addition, any esoteric OS that supports the php_uname function can be used. Note that
the "unix" OS is defined as any of linux, freebsd, darwin,
sunos, irix, hpux, or aix.
The arch dependency is used to restrict a package to a specific os and processor architecture. Here is an example:
To specify that a package can be installed on every architecture except the one specified, use the <conflicts/> tag:
The arch pattern is defined by the OS_Guess->matchSignature method, and is as
follows: sysname[-release[-cpu[-extra]]]. All segments within
[] are optional, and the wildcard "*" can be used in all
segments instead of a value. In addition, the "?" wildcard can
be used to specify a single character that can match any value.
i?86 will match i386, i686, i586 and so on.
sysname is the same as the os dependency, except unix is not supported.
release is the version of the operating system.
cpu is the specific cpu, and is typically i?86, sparc, powerpc.
extra is any other stuff on the end of php_uname, including the glibc version
<usesrole> - documenting custom file roles used in <contents>
Standard file roles provided by default with PEAR are:
php
data
doc
test
script
src
ext
If your package chooses to use a role provided by a third party that implements some more advanced file installation handling, all you need to do is specify the role in the xml for the <file> tag that contains it like so:
However, if a user does not have the package installed that provides the custom role "foo", then the error message on installation will simply say "unknown role 'foo'", which is not very helpful.
The <usesrole> tag instead prompts the installer to tell the user "this package uses the custom role 'foo', install package pear.example.com/Foo to use"
Note that static URI packages (channel-less packages) are also supported:
<usestask> - documenting custom tasks used in <contents>
Standard file tasks provided by default with PEAR are documented in this location.
If your package chooses to use a task provided by a third party, all you need to do is specify the task as part of the xml for the <file> tag that contains it like so:
However, if a user does not have the package installed that provides the custom task "foo", then the error message on installation will simply say "unknown task 'foo'", which is not very helpful.
The <usestask> tag instead prompts the installer to tell the user "this package uses the custom task 'foo', install package pear.example.com/Foo to use"
Note that static URI packages (channel-less packages) are also supported:
<phprelease>, <extbinrelease>, <extsrcrelease>, <bundle> - specifying the content type of a release
In package.xml 1.0, there was one release type. package.xml 2.0 provides much finer control over the kind of release in order to provide three new release types: extension binary release, extension source release, and package bundle release.
All of the normal release tags (phprelease, extsrcrelease, extbinrelease) may contain two optional sections, <installconditions> and <filelist>. The purpose of these sections is to allow specification of different file install groups based on the target OS for installation, or other common install conditions.
To be clear: in package.xml, there was 1 <release> tag. package.xml 2.0 allows several adjacent release tags, each specifying a different install set. This actually simplifies complex installation filesets by separating the contents listing of the tarball from how the installer should manipulate this listing. Debugging installation file sets should be much simpler with this change.
The <filelist> tag can contain only two possible tags, <install> and <ignore>. install has two required attributes, "name" and "as". The install tag is used in the same manner as package.xml's install-as attribute for the <file>, to specify a new installation location for a file in the contents list. The ignore tag is used to completely ignore a file.
The <installconditions> tag can contain 4 tags whose format can be found in the <dependencies> section: <php>, <extension>, <os>, and <arch>. Each tag can appear exactly once except for the extension tag, which can appear limitless times.
The php tag is used to specify a php version or range of versions that an install set should be valid with.
The extension tag is used to specify extensions that must be present for an install set to be valid.
The os tag is used to specify an OS that must be present for an install set to be valid. Note that unix can be used to match all flavors, and linux can be used to match all linux-based OSes. Darwin should be used for Mac OS X, and * can be used to match all operating systems.
The arch tag is used to specify a uname string or portion of a uname string that must match in order for the install set to be valid.
The phprelease release type is designed for PEAR-style PHP script package releases. It causes a few specific validation changes. First of all, the <contents> tag must contain <file> and <dir> tags. The only valid roles for files are role="php", role="data", role="doc", and role="test" plus any custom roles that the user has installed for use in php releases.
The extsrcrelease release type is for PECL-style PHP extension releases that must be compiled in order to be useable. It causes a few specific validation changes. First of all, the <contents> tag must contain <file> and <dir> tags. The only valid roles for files are role="src", role="data", role="doc", and role="test" plus any custom roles that the user has installed for use in extension source releases.
In addition, the <providesextension> tag must be present in order to document the name of the extension this package provides must be in the package.xml as well.
The extbinrelease release type is for PECL-style PHP Extension binary releases that are pre-compiled. It causes a few specific validation changes. First of all, the <contents> tag must contain <file> and <dir> tags. The only valid roles for files are role="ext", role="data", role="doc", and role="test" plus any custom roles that the user has installed for use in extension binary releases.
In addition, the <srcpackage> or <srcuri> and the <providesextension> tags must be present in order to document the package that provides extension source for this binary release, and the name of the extension this package provides must be in the package.xml as well.
The bundle release type is designed to allow packaging several other package releases into a single bundle of packages that will all be installed at the same time. This can be used to distribute a complete application as one tarball, or to distribute a library of packages in a single tarball.
Unlike the other release types, a bundle release's <contents> tag must contain only the <bundledpackage> tag. The contents of the bundledpackage should be release names like "Foo-1.2.3.tgz"
In addition, the <bundle/> tag must be empty.
| PEAR_PackageFileManager : The Definitive Guide | v 1.6.0 : November 17, 2006 |