94 |
jpm |
1 |
<?php
|
|
|
2 |
//
|
|
|
3 |
// +------------------------------------------------------------------------+
|
|
|
4 |
// | PEAR :: Package File Manager |
|
|
|
5 |
// +------------------------------------------------------------------------+
|
|
|
6 |
// | Copyright (c) 2003-2004 Gregory Beaver |
|
|
|
7 |
// | Email cellog@phpdoc.org |
|
|
|
8 |
// +------------------------------------------------------------------------+
|
|
|
9 |
// | This source file is subject to version 3.00 of the PHP License, |
|
|
|
10 |
// | that is available at http://www.php.net/license/3_0.txt. |
|
|
|
11 |
// | If you did not receive a copy of the PHP license and are unable to |
|
|
|
12 |
// | obtain it through the world-wide-web, please send a note to |
|
|
|
13 |
// | license@php.net so we can mail you a copy immediately. |
|
|
|
14 |
// +------------------------------------------------------------------------+
|
|
|
15 |
// | Portions of this code based on phpDocumentor |
|
|
|
16 |
// | Web http://www.phpdoc.org |
|
|
|
17 |
// | Mirror http://phpdocu.sourceforge.net/ |
|
|
|
18 |
// +------------------------------------------------------------------------+
|
|
|
19 |
// $Id: PackageFileManager.php,v 1.42 2005/04/06 22:21:20 cellog Exp $
|
|
|
20 |
//
|
|
|
21 |
|
|
|
22 |
/**
|
|
|
23 |
* @package PEAR_PackageFileManager
|
|
|
24 |
*/
|
|
|
25 |
/**
|
|
|
26 |
* PEAR installer
|
|
|
27 |
*/
|
|
|
28 |
require_once 'PEAR/Common.php';
|
|
|
29 |
/**#@+
|
|
|
30 |
* Error Codes
|
|
|
31 |
*/
|
|
|
32 |
define('PEAR_PACKAGEFILEMANAGER_NOSTATE', 1);
|
|
|
33 |
define('PEAR_PACKAGEFILEMANAGER_NOVERSION', 2);
|
|
|
34 |
define('PEAR_PACKAGEFILEMANAGER_NOPKGDIR', 3);
|
|
|
35 |
define('PEAR_PACKAGEFILEMANAGER_NOBASEDIR', 4);
|
|
|
36 |
define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND', 5);
|
|
|
37 |
define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE', 6);
|
|
|
38 |
define('PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE', 7);
|
|
|
39 |
define('PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE', 8);
|
|
|
40 |
define('PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE', 9);
|
|
|
41 |
define('PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE', 10);
|
|
|
42 |
define('PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST', 11);
|
|
|
43 |
define('PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES', 12);
|
|
|
44 |
define('PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST', 13);
|
|
|
45 |
define('PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS', 14);
|
|
|
46 |
define('PEAR_PACKAGEFILEMANAGER_NOPACKAGE', 15);
|
|
|
47 |
define('PEAR_PACKAGEFILEMANAGER_WRONG_MROLE', 16);
|
|
|
48 |
define('PEAR_PACKAGEFILEMANAGER_NOSUMMARY', 17);
|
|
|
49 |
define('PEAR_PACKAGEFILEMANAGER_NODESC', 18);
|
|
|
50 |
define('PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS', 19);
|
|
|
51 |
define('PEAR_PACKAGEFILEMANAGER_NO_FILES', 20);
|
|
|
52 |
define('PEAR_PACKAGEFILEMANAGER_IGNORED_EVERYTHING', 21);
|
|
|
53 |
define('PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE', 22);
|
|
|
54 |
define('PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE', 23);
|
|
|
55 |
define('PEAR_PACKAGEFILEMANAGER_INVALID_ROLE', 24);
|
|
|
56 |
define('PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE', 25);
|
|
|
57 |
define('PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED', 26);
|
|
|
58 |
define('PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO', 27);
|
|
|
59 |
/**#@-*/
|
|
|
60 |
/**
|
|
|
61 |
* Error messages
|
|
|
62 |
* @global array $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS']
|
|
|
63 |
*/
|
|
|
64 |
$GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'] =
|
|
|
65 |
array(
|
|
|
66 |
'en' =>
|
|
|
67 |
array(
|
|
|
68 |
PEAR_PACKAGEFILEMANAGER_NOSTATE =>
|
|
|
69 |
'Release State (option \'state\') must by specified in PEAR_PackageFileManager setOptions (alpha|beta|stable)',
|
|
|
70 |
PEAR_PACKAGEFILEMANAGER_NOVERSION =>
|
|
|
71 |
'Release Version (option \'version\') must be specified in PEAR_PackageFileManager setOptions',
|
|
|
72 |
PEAR_PACKAGEFILEMANAGER_NOPKGDIR =>
|
|
|
73 |
'Package source base directory (option \'packagedirectory\') must be ' .
|
|
|
74 |
'specified in PEAR_PackageFileManager setOptions',
|
|
|
75 |
PEAR_PACKAGEFILEMANAGER_NOBASEDIR =>
|
|
|
76 |
'Package install base directory (option \'baseinstalldir\') must be ' .
|
|
|
77 |
'specified in PEAR_PackageFileManager setOptions',
|
|
|
78 |
PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND =>
|
|
|
79 |
'Base class "%s" can\'t be located',
|
|
|
80 |
PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE =>
|
|
|
81 |
'Base class "%s" can\'t be located in default or user-specified directories',
|
|
|
82 |
PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE =>
|
|
|
83 |
'Failed to write package.xml file to destination directory',
|
|
|
84 |
PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE =>
|
|
|
85 |
'Destination directory "%s" is unwritable',
|
|
|
86 |
PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE =>
|
|
|
87 |
'Failed to copy package.xml.tmp file to package.xml',
|
|
|
88 |
PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE =>
|
|
|
89 |
'Failed to open temporary file "%s" for writing',
|
|
|
90 |
PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST =>
|
|
|
91 |
'package.xml file path "%s" doesn\'t exist or isn\'t a directory',
|
|
|
92 |
PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES =>
|
|
|
93 |
'Directory "%s" is not a CVS directory (it must have the CVS/Entries file)',
|
|
|
94 |
PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST =>
|
|
|
95 |
'Package source base directory "%s" doesn\'t exist or isn\'t a directory',
|
|
|
96 |
PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS =>
|
|
|
97 |
'Run $managerclass->setOptions() before any other methods',
|
|
|
98 |
PEAR_PACKAGEFILEMANAGER_NOPACKAGE =>
|
|
|
99 |
'Package Name (option \'package\') must by specified in PEAR_PackageFileManager '.
|
|
|
100 |
'setOptions to create a new package.xml',
|
|
|
101 |
PEAR_PACKAGEFILEMANAGER_NOSUMMARY =>
|
|
|
102 |
'Package Summary (option \'summary\') must by specified in PEAR_PackageFileManager' .
|
|
|
103 |
' setOptions to create a new package.xml',
|
|
|
104 |
PEAR_PACKAGEFILEMANAGER_NODESC =>
|
|
|
105 |
'Detailed Package Description (option \'description\') must be' .
|
|
|
106 |
' specified in PEAR_PackageFileManager setOptions to create a new package.xml',
|
|
|
107 |
PEAR_PACKAGEFILEMANAGER_WRONG_MROLE =>
|
|
|
108 |
'Maintainer role must be one of "%s", was "%s"',
|
|
|
109 |
PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS =>
|
|
|
110 |
'Add maintainers to a package before generating the package.xml',
|
|
|
111 |
PEAR_PACKAGEFILEMANAGER_NO_FILES =>
|
|
|
112 |
'No files found, check the path "%s"',
|
|
|
113 |
PEAR_PACKAGEFILEMANAGER_IGNORED_EVERYTHING =>
|
|
|
114 |
'No files left, check the path "%s" and ignore option "%s"',
|
|
|
115 |
PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE =>
|
|
|
116 |
'Package validation failed:%s%s',
|
|
|
117 |
PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE =>
|
|
|
118 |
'Replacement Type must be one of "%s", was passed "%s"',
|
|
|
119 |
PEAR_PACKAGEFILEMANAGER_INVALID_ROLE =>
|
|
|
120 |
'Invalid file role passed to addRole, must be one of "%s", was passed "%s"',
|
|
|
121 |
PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE =>
|
|
|
122 |
'addDependency had PHP as a package, use type="php"',
|
|
|
123 |
PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED =>
|
|
|
124 |
'path "%path%" contains CVS directory',
|
|
|
125 |
PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO =>
|
|
|
126 |
'PHP_Compat is not installed, cannot detect dependencies',
|
|
|
127 |
),
|
|
|
128 |
// other language translations go here
|
|
|
129 |
);
|
|
|
130 |
/**
|
|
|
131 |
* PEAR :: PackageFileManager updates the <filelist></filelist> section
|
|
|
132 |
* of a PEAR package.xml file to reflect the current files in
|
|
|
133 |
* preparation for a release.
|
|
|
134 |
*
|
|
|
135 |
* The PEAR_PackageFileManager class uses a plugin system to generate the
|
|
|
136 |
* list of files in a package. This allows both standard recursive
|
|
|
137 |
* directory parsing (plugin type file) and more intelligent options
|
|
|
138 |
* such as the CVS browser {@link PEAR_PackageFileManager_Cvs}, which
|
|
|
139 |
* grabs all files in a local CVS checkout to create the list, ignoring
|
|
|
140 |
* any other local files.
|
|
|
141 |
*
|
|
|
142 |
* Other options include specifying roles for file extensions (all .php
|
|
|
143 |
* files are role="php", for example), roles for directories (all directories
|
|
|
144 |
* named "tests" are given role="tests" by default), and exceptions.
|
|
|
145 |
* Exceptions are specific pathnames with * and ? wildcards that match
|
|
|
146 |
* a default role, but should have another. For example, perhaps
|
|
|
147 |
* a debug.tpl template would normally be data, but should be included
|
|
|
148 |
* in the docs role. Along these lines, to exclude files entirely,
|
|
|
149 |
* use the ignore option.
|
|
|
150 |
*
|
|
|
151 |
* Required options for a release include version, baseinstalldir, state,
|
|
|
152 |
* and packagedirectory (the full path to the local location of the
|
|
|
153 |
* package to create a package.xml file for)
|
|
|
154 |
*
|
|
|
155 |
* Example usage:
|
|
|
156 |
* <code>
|
|
|
157 |
* <?php
|
|
|
158 |
* require_once('PEAR/PackageFileManager.php');
|
|
|
159 |
* $packagexml = new PEAR_PackageFileManager;
|
|
|
160 |
* $e = $packagexml->setOptions(
|
|
|
161 |
* array('baseinstalldir' => 'PhpDocumentor',
|
|
|
162 |
* 'version' => '1.2.1',
|
|
|
163 |
* 'packagedirectory' => 'C:/Web Pages/chiara/phpdoc2/',
|
|
|
164 |
* 'state' => 'stable',
|
|
|
165 |
* 'filelistgenerator' => 'cvs', // generate from cvs, use file for directory
|
|
|
166 |
* 'notes' => 'We\'ve implemented many new and exciting features',
|
|
|
167 |
* 'ignore' => array('TODO', 'tests/'), // ignore TODO, all files in tests/
|
|
|
168 |
* 'installexceptions' => array('phpdoc' => '/*'), // baseinstalldir ="/" for phpdoc
|
|
|
169 |
* 'dir_roles' => array('tutorials' => 'doc'),
|
|
|
170 |
* 'exceptions' => array('README' => 'doc', // README would be data, now is doc
|
|
|
171 |
* 'PHPLICENSE.txt' => 'doc'))); // same for the license
|
|
|
172 |
* if (PEAR::isError($e)) {
|
|
|
173 |
* echo $e->getMessage();
|
|
|
174 |
* die();
|
|
|
175 |
* }
|
|
|
176 |
* $e = $test->addPlatformException('pear-phpdoc.bat', 'windows');
|
|
|
177 |
* if (PEAR::isError($e)) {
|
|
|
178 |
* echo $e->getMessage();
|
|
|
179 |
* exit;
|
|
|
180 |
* }
|
|
|
181 |
* $packagexml->addRole('pkg', 'doc'); // add a new role mapping
|
|
|
182 |
* if (PEAR::isError($e)) {
|
|
|
183 |
* echo $e->getMessage();
|
|
|
184 |
* exit;
|
|
|
185 |
* }
|
|
|
186 |
* // replace @PHP-BIN@ in this file with the path to php executable! pretty neat
|
|
|
187 |
* $e = $test->addReplacement('pear-phpdoc', 'pear-config', '@PHP-BIN@', 'php_bin');
|
|
|
188 |
* if (PEAR::isError($e)) {
|
|
|
189 |
* echo $e->getMessage();
|
|
|
190 |
* exit;
|
|
|
191 |
* }
|
|
|
192 |
* $e = $test->addReplacement('pear-phpdoc.bat', 'pear-config', '@PHP-BIN@', 'php_bin');
|
|
|
193 |
* if (PEAR::isError($e)) {
|
|
|
194 |
* echo $e->getMessage();
|
|
|
195 |
* exit;
|
|
|
196 |
* }
|
|
|
197 |
* // note use of {@link debugPackageFile()} - this is VERY important
|
|
|
198 |
* if (isset($_GET['make']) || (isset($_SERVER['argv'][2]) &&
|
|
|
199 |
* $_SERVER['argv'][2] == 'make')) {
|
|
|
200 |
* $e = $packagexml->writePackageFile();
|
|
|
201 |
* } else {
|
|
|
202 |
* $e = $packagexml->debugPackageFile();
|
|
|
203 |
* }
|
|
|
204 |
* if (PEAR::isError($e)) {
|
|
|
205 |
* echo $e->getMessage();
|
|
|
206 |
* die();
|
|
|
207 |
* }
|
|
|
208 |
* ?>
|
|
|
209 |
* </code>
|
|
|
210 |
*
|
|
|
211 |
* In addition, a package.xml file can now be generated from
|
|
|
212 |
* scratch, with the usage of new options package, summary, description, and
|
|
|
213 |
* the use of the {@link addMaintainer()} method
|
|
|
214 |
* @package PEAR_PackageFileManager
|
|
|
215 |
*/
|
|
|
216 |
class PEAR_PackageFileManager
|
|
|
217 |
{
|
|
|
218 |
/**
|
|
|
219 |
* Format: array(array(regexp-ready string to search for whole path,
|
|
|
220 |
* regexp-ready string to search for basename of ignore strings),...)
|
|
|
221 |
* @var false|array
|
|
|
222 |
* @access private
|
|
|
223 |
*/
|
|
|
224 |
var $_ignore = false;
|
|
|
225 |
|
|
|
226 |
/**
|
|
|
227 |
* Contents of the package.xml file
|
|
|
228 |
* @var string
|
|
|
229 |
* @access private
|
|
|
230 |
*/
|
|
|
231 |
var $_packageXml = false;
|
|
|
232 |
|
|
|
233 |
/**
|
|
|
234 |
* Contents of the original package.xml file, if any
|
|
|
235 |
* @var string
|
|
|
236 |
* @access private
|
|
|
237 |
*/
|
|
|
238 |
var $_oldPackageXml = false;
|
|
|
239 |
|
|
|
240 |
/**
|
|
|
241 |
* @access private
|
|
|
242 |
* @var PEAR_Common
|
|
|
243 |
*/
|
|
|
244 |
var $_pear;
|
|
|
245 |
|
|
|
246 |
/**
|
|
|
247 |
* @access private
|
|
|
248 |
* @var array
|
|
|
249 |
*/
|
|
|
250 |
var $_warningStack = array();
|
|
|
251 |
|
|
|
252 |
/**
|
|
|
253 |
* flag used to determine whether to use PHP_CompatInfo to detect deps
|
|
|
254 |
* @var boolean
|
|
|
255 |
* @access private
|
|
|
256 |
*/
|
|
|
257 |
var $_detectDependencies = false;
|
|
|
258 |
|
|
|
259 |
/**
|
|
|
260 |
* @access private
|
|
|
261 |
* @var string
|
|
|
262 |
*/
|
|
|
263 |
var $_options = array(
|
|
|
264 |
'packagefile' => 'package.xml',
|
|
|
265 |
'doctype' => 'http://pear.php.net/dtd/package-1.0',
|
|
|
266 |
'filelistgenerator' => 'file',
|
|
|
267 |
'license' => 'PHP License',
|
|
|
268 |
'changelogoldtonew' => true,
|
|
|
269 |
'roles' =>
|
|
|
270 |
array(
|
|
|
271 |
'php' => 'php',
|
|
|
272 |
'html' => 'doc',
|
|
|
273 |
'*' => 'data',
|
|
|
274 |
),
|
|
|
275 |
'dir_roles' =>
|
|
|
276 |
array(
|
|
|
277 |
'docs' => 'doc',
|
|
|
278 |
'examples' => 'doc',
|
|
|
279 |
'tests' => 'test',
|
|
|
280 |
),
|
|
|
281 |
'exceptions' => array(),
|
|
|
282 |
'installexceptions' => array(),
|
|
|
283 |
'installas' => array(),
|
|
|
284 |
'platformexceptions' => array(),
|
|
|
285 |
'scriptphaseexceptions' => array(),
|
|
|
286 |
'ignore' => array(),
|
|
|
287 |
'include' => false,
|
|
|
288 |
'deps' => false,
|
|
|
289 |
'maintainers' => false,
|
|
|
290 |
'notes' => '',
|
|
|
291 |
'changelognotes' => false,
|
|
|
292 |
'outputdirectory' => false,
|
|
|
293 |
'pathtopackagefile' => false,
|
|
|
294 |
'lang' => 'en',
|
|
|
295 |
'configure_options' => array(),
|
|
|
296 |
'replacements' => array(),
|
|
|
297 |
'pearcommonclass' => false,
|
|
|
298 |
'simpleoutput' => false,
|
|
|
299 |
'addhiddenfiles' => false,
|
|
|
300 |
'cleardependencies' => false,
|
|
|
301 |
);
|
|
|
302 |
|
|
|
303 |
/**
|
|
|
304 |
* Does nothing, use setOptions
|
|
|
305 |
*
|
|
|
306 |
* The constructor is not used in order to be able to
|
|
|
307 |
* return a PEAR_Error from setOptions
|
|
|
308 |
* @see setOptions()
|
|
|
309 |
*/
|
|
|
310 |
function PEAR_PackageFileManager()
|
|
|
311 |
{
|
|
|
312 |
}
|
|
|
313 |
|
|
|
314 |
/**
|
|
|
315 |
* Set package.xml generation options
|
|
|
316 |
*
|
|
|
317 |
* The options array is indexed as follows:
|
|
|
318 |
* <code>
|
|
|
319 |
* $options = array('option_name' => <optionvalue>);
|
|
|
320 |
* </code>
|
|
|
321 |
*
|
|
|
322 |
* The documentation below simplifies this description through
|
|
|
323 |
* the use of option_name without quotes
|
|
|
324 |
*
|
|
|
325 |
* Configuration options:
|
|
|
326 |
* - lang: lang controls the language in which error messages are
|
|
|
327 |
* displayed. There are currently only English error messages,
|
|
|
328 |
* but any contributed will be added over time.<br>
|
|
|
329 |
* Possible values: en (default)
|
|
|
330 |
* - packagefile: the name of the packagefile, defaults to package.xml
|
|
|
331 |
* - pathtopackagefile: the path to an existing package file to read in,
|
|
|
332 |
* if different from the packagedirectory
|
|
|
333 |
* - packagedirectory: the path to the base directory of the package. For
|
|
|
334 |
* package PEAR_PackageFileManager, this path is
|
|
|
335 |
* /path/to/pearcvs/pear/PEAR_PackageFileManager where
|
|
|
336 |
* /path/to/pearcvs is a local path on your hard drive
|
|
|
337 |
* - outputdirectory: the path in which to place the generated package.xml
|
|
|
338 |
* by default, this is ignored, and the package.xml is
|
|
|
339 |
* created in the packagedirectory
|
|
|
340 |
* - filelistgenerator: the <filelist> section plugin which will be used.
|
|
|
341 |
* In this release, there are two generator plugins,
|
|
|
342 |
* file and cvs. For details, see the docs for these
|
|
|
343 |
* plugins
|
|
|
344 |
* - usergeneratordir: For advanced users. If you write your own filelist
|
|
|
345 |
* generator plugin, use this option to tell
|
|
|
346 |
* PEAR_PackageFileManager where to find the file that
|
|
|
347 |
* contains it. If the plugin is named foo, the class
|
|
|
348 |
* must be named PEAR_PackageFileManager_Foo
|
|
|
349 |
* no matter where it is located. By default, the Foo
|
|
|
350 |
* plugin is located in PEAR/PackageFileManager/Foo.php.
|
|
|
351 |
* If you pass /path/to/foo in this option, setOptions
|
|
|
352 |
* will look for PEAR_PackageFileManager_Foo in
|
|
|
353 |
* /path/to/foo/Foo.php
|
|
|
354 |
* - doctype: Specifies the DTD of the package.xml file. Default is
|
|
|
355 |
* http://pear.php.net/dtd/package-1.0
|
|
|
356 |
* - pearcommonclass: Specifies the name of the class to instantiate, default
|
|
|
357 |
* is PEAR_Common, but users can override this with a custom
|
|
|
358 |
* class that implements PEAR_Common's method interface
|
|
|
359 |
* - changelogoldtonew: True if the ChangeLog should list from oldest entry to
|
|
|
360 |
* newest. Set to false if you would like new entries first
|
|
|
361 |
* - simpleoutput: True if the package.xml should not contain md5sum or <provides />
|
|
|
362 |
* for readability
|
|
|
363 |
* - addhiddenfiles: True if you wish to add hidden files/directories that begin with .
|
|
|
364 |
* like .bashrc. This is only used by the File generator. The CVS
|
|
|
365 |
* generator will use all files in CVS regardless of format
|
|
|
366 |
*
|
|
|
367 |
* package.xml simple options:
|
|
|
368 |
* - baseinstalldir: The base directory to install this package in. For
|
|
|
369 |
* package PEAR_PackageFileManager, this is "PEAR", for
|
|
|
370 |
* package PEAR, this is "/"
|
|
|
371 |
* - license: The license this release is released under. Default is
|
|
|
372 |
* PHP License if left unspecified
|
|
|
373 |
* - notes: Release notes, any text describing what makes this release unique
|
|
|
374 |
* - changelognotes: notes for the changelog, this should be more detailed than
|
|
|
375 |
* the release notes. By default, PEAR_PackageFileManager uses
|
|
|
376 |
* the notes option for the changelog as well
|
|
|
377 |
* - version: The version number for this release. Remember the convention for
|
|
|
378 |
* numbering: initial alpha is between 0 and 1, add b<beta number> for
|
|
|
379 |
* beta as in 1.0b1, the integer portion of the version should specify
|
|
|
380 |
* backwards compatibility, as in 1.1 is backwards compatible with 1.0,
|
|
|
381 |
* but 2.0 is not backwards compatible with 1.10. Also note that 1.10
|
|
|
382 |
* is a greater release version than 1.1 (think of it as "one point ten"
|
|
|
383 |
* and "one point one"). Bugfix releases should be a third decimal as in
|
|
|
384 |
* 1.0.1, 1.0.2
|
|
|
385 |
* - package: [optional] Package name. Use this to create a new package.xml, or
|
|
|
386 |
* overwrite an existing one from another package used as a template
|
|
|
387 |
* - summary: [optional] Summary of package purpose
|
|
|
388 |
* - description: [optional] Description of package purpose. Note that the above
|
|
|
389 |
* three options are not optional when creating a new package.xml
|
|
|
390 |
* from scratch
|
|
|
391 |
*
|
|
|
392 |
* <b>WARNING</b>: all complex options that require a file path are case-sensitive
|
|
|
393 |
*
|
|
|
394 |
* package.xml complex options:
|
|
|
395 |
* - cleardependencies: since version 1.3.0, this option will erase any existing
|
|
|
396 |
* dependencies in the package.xml if set to true
|
|
|
397 |
* - ignore: an array of filenames, directory names, or wildcard expressions specifying
|
|
|
398 |
* files to exclude entirely from the package.xml. Wildcards are operating system
|
|
|
399 |
* wildcards * and ?. file*foo.php will exclude filefoo.php, fileabrfoo.php and
|
|
|
400 |
* filewho_is_thisfoo.php. file?foo.php will exclude fileafoo.php and will not
|
|
|
401 |
* exclude fileaafoo.php. test/ will exclude all directories and subdirectories of
|
|
|
402 |
* ANY directory named test encountered in directory parsing. *test* will exclude
|
|
|
403 |
* all files and directories that contain test in their name
|
|
|
404 |
* - include: an array of filenames, directory names, or wildcard expressions specifying
|
|
|
405 |
* files to include in the listing. All other files will be ignored.
|
|
|
406 |
* Wildcards are in the same format as ignore
|
|
|
407 |
* - roles: this is an array mapping file extension to install role. This
|
|
|
408 |
* specifies default behavior that can be overridden by the exceptions
|
|
|
409 |
* option and dir_roles option. use {@link addRole()} to add a new
|
|
|
410 |
* role to the pre-existing array
|
|
|
411 |
* - dir_roles: this is an array mapping directory name to install role. All
|
|
|
412 |
* files in a directory whose name matches the directory will be
|
|
|
413 |
* given the install role specified. Single files can be excluded
|
|
|
414 |
* from this using the exceptions option. The directory should be
|
|
|
415 |
* a relative path from the baseinstalldir, or "/" for the baseinstalldir
|
|
|
416 |
* - exceptions: specify file role for specific files. This array maps all files
|
|
|
417 |
* matching the exact name of a file to a role as in "file.ext" => "role"
|
|
|
418 |
* - deps: dependency array. Pass in an empty array to clear all dependencies, and use
|
|
|
419 |
* {@link addDependency()} to add new ones/replace existing ones
|
|
|
420 |
* - maintainers: maintainers array. Pass in an empty array to clear all maintainers, and
|
|
|
421 |
* use {@link addMaintainer()} to add a new maintainer/replace existing maintainer
|
|
|
422 |
* - installexceptions: array mapping of specific filenames to baseinstalldir values. Use
|
|
|
423 |
* this to force the installation of a file into another directory,
|
|
|
424 |
* such as forcing a script to be in the root scripts directory so that
|
|
|
425 |
* it will be in the path. The filename must be a relative path to the
|
|
|
426 |
* packagedirectory
|
|
|
427 |
* - platformexceptions: array mapping of specific filenames to the platform they should be
|
|
|
428 |
* installed on. Use this to specify unix-only files or windows-only
|
|
|
429 |
* files. The format of the platform string must be
|
|
|
430 |
* OS-version-cpu-extra if any more specific information is needed,
|
|
|
431 |
* and the OS must be in lower case as in "windows." The match is
|
|
|
432 |
* performed using a regular expression, but uses * and ? wildcards
|
|
|
433 |
* instead of .* and .?. Note that hpux/aix/irix/linux are all
|
|
|
434 |
* exclusive. To select non-windows, use (*ix|*ux)
|
|
|
435 |
* - scriptphaseexceptions: array mapping of scripts to their install phase. This can be
|
|
|
436 |
* one of: pre-install, post-install, pre-uninstall, post-uninstall,
|
|
|
437 |
* pre-build, post-build, pre-setup, or post-setup
|
|
|
438 |
* - installas: array mapping of specific filenames to the filename they should be installed as.
|
|
|
439 |
* Use this to specify new filenames for files that should be installed. This will
|
|
|
440 |
* often be used in conjunction with platformexceptions if there are two files for
|
|
|
441 |
* different OSes that must have the same name when installed.
|
|
|
442 |
* - replacements: array mapping of specific filenames to complex text search-and-replace that
|
|
|
443 |
* should be performed upon install. The format is:
|
|
|
444 |
* <pre>
|
|
|
445 |
* filename => array('type' => php-const|pear-config|package-info
|
|
|
446 |
* 'from' => text in file
|
|
|
447 |
* 'to' => name of variable)
|
|
|
448 |
* </pre>
|
|
|
449 |
* if type is php-const, then 'to' must be the name of a PHP Constant.
|
|
|
450 |
* If type is pear-config, then 'to' must be the name of a PEAR config
|
|
|
451 |
* variable accessible through a PEAR_Config class->get() method. If
|
|
|
452 |
* type is package-info, then 'to' must be the name of a section from
|
|
|
453 |
* the package.xml file used to install this file.
|
|
|
454 |
* - globalreplacements: a list of replacements that should be performed on every single file.
|
|
|
455 |
* The format is the same as replacements (since 1.4.0)
|
|
|
456 |
* - configure_options: array specifies build options for PECL packages (you should probably
|
|
|
457 |
* use PECL_Gen instead, but it's here for completeness)
|
|
|
458 |
* @see PEAR_PackageFileManager_File
|
|
|
459 |
* @see PEAR_PackageFileManager_CVS
|
|
|
460 |
* @return void|PEAR_Error
|
|
|
461 |
* @throws PEAR_PACKAGEFILEMANAGER_NOSTATE
|
|
|
462 |
* @throws PEAR_PACKAGEFILEMANAGER_NOVERSION
|
|
|
463 |
* @throws PEAR_PACKAGEFILEMANAGER_NOPKGDIR
|
|
|
464 |
* @throws PEAR_PACKAGEFILEMANAGER_NOBASEDIR
|
|
|
465 |
* @throws PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE
|
|
|
466 |
* @throws PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND
|
|
|
467 |
* @param array
|
|
|
468 |
*/
|
|
|
469 |
function setOptions($options = array(), $internal = false)
|
|
|
470 |
{
|
|
|
471 |
if (!$internal) {
|
|
|
472 |
if (!isset($options['state'])) {
|
|
|
473 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSTATE);
|
|
|
474 |
}
|
|
|
475 |
if (!isset($options['version'])) {
|
|
|
476 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOVERSION);
|
|
|
477 |
}
|
|
|
478 |
}
|
|
|
479 |
if (!isset($options['packagedirectory']) && !$internal) {
|
|
|
480 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPKGDIR);
|
|
|
481 |
} elseif (isset($options['packagedirectory'])) {
|
|
|
482 |
$options['packagedirectory'] = str_replace(DIRECTORY_SEPARATOR,
|
|
|
483 |
'/',
|
|
|
484 |
realpath($options['packagedirectory']));
|
|
|
485 |
if ($options['packagedirectory']{strlen($options['packagedirectory']) - 1} != '/') {
|
|
|
486 |
$options['packagedirectory'] .= '/';
|
|
|
487 |
}
|
|
|
488 |
}
|
|
|
489 |
if (isset($options['pathtopackagefile'])) {
|
|
|
490 |
$options['pathtopackagefile'] = str_replace(DIRECTORY_SEPARATOR,
|
|
|
491 |
'/',
|
|
|
492 |
realpath($options['pathtopackagefile']));
|
|
|
493 |
if ($options['pathtopackagefile']{strlen($options['pathtopackagefile']) - 1} != '/') {
|
|
|
494 |
$options['pathtopackagefile'] .= '/';
|
|
|
495 |
}
|
|
|
496 |
}
|
|
|
497 |
if (!isset($options['baseinstalldir']) && !$internal) {
|
|
|
498 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOBASEDIR);
|
|
|
499 |
}
|
|
|
500 |
$this->_options = array_merge($this->_options, $options);
|
|
|
501 |
|
|
|
502 |
if (!class_exists($this->_options['pearcommonclass'])) {
|
|
|
503 |
if ($this->_options['simpleoutput']) {
|
|
|
504 |
if ($this->isIncludeable('PEAR/PackageFile/Generator/v1.php')) {
|
|
|
505 |
include_once 'PEAR/PackageFileManager/SimpleGenerator.php';
|
|
|
506 |
$this->_options['pearcommonclass'] = 'PEAR_PackageFileManager_SimpleGenerator';
|
|
|
507 |
} else {
|
|
|
508 |
include_once 'PEAR/PackageFileManager/XMLOutput.php';
|
|
|
509 |
$this->_options['pearcommonclass'] = 'PEAR_PackageFileManager_XMLOutput';
|
|
|
510 |
}
|
|
|
511 |
} else {
|
|
|
512 |
$this->_options['pearcommonclass'] = 'PEAR_Common';
|
|
|
513 |
}
|
|
|
514 |
}
|
|
|
515 |
$path = ($this->_options['pathtopackagefile'] ?
|
|
|
516 |
$this->_options['pathtopackagefile'] : $this->_options['packagedirectory']);
|
|
|
517 |
$this->_options['filelistgenerator'] =
|
|
|
518 |
ucfirst(strtolower($this->_options['filelistgenerator']));
|
|
|
519 |
if (!$internal) {
|
|
|
520 |
if (PEAR::isError($res =
|
|
|
521 |
$this->_getExistingPackageXML($path, $this->_options['packagefile']))) {
|
|
|
522 |
return $res;
|
|
|
523 |
}
|
|
|
524 |
}
|
|
|
525 |
if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) {
|
|
|
526 |
// attempt to load the interface from the standard PEAR location
|
|
|
527 |
if ($this->isIncludeable('PEAR/PackageFileManager/' .
|
|
|
528 |
$this->_options['filelistgenerator'] . '.php')) {
|
|
|
529 |
include_once('PEAR/PackageFileManager/' .
|
|
|
530 |
$this->_options['filelistgenerator'] . '.php');
|
|
|
531 |
} elseif (isset($this->_options['usergeneratordir'])) {
|
|
|
532 |
// attempt to load from a user-specified directory
|
|
|
533 |
if (is_dir(realpath($this->_options['usergeneratordir']))) {
|
|
|
534 |
$this->_options['usergeneratordir'] =
|
|
|
535 |
str_replace(DIRECTORY_SEPARATOR,
|
|
|
536 |
'/',
|
|
|
537 |
realpath($this->_options['usergeneratordir']));
|
|
|
538 |
if ($this->_options['usergeneratordir']{strlen($this->_options['usergeneratordir'])
|
|
|
539 |
- 1} != '/') {
|
|
|
540 |
$this->_options['usergeneratordir'] .= '/';
|
|
|
541 |
}
|
|
|
542 |
} else {
|
|
|
543 |
$this->_options['usergeneratordir'] = '////';
|
|
|
544 |
}
|
|
|
545 |
if (file_exists($this->_options['usergeneratordir'] .
|
|
|
546 |
$this->_options['filelistgenerator'] . '.php') &&
|
|
|
547 |
is_readable($this->_options['usergeneratordir'] .
|
|
|
548 |
$this->_options['filelistgenerator'] . '.php')) {
|
|
|
549 |
include_once($this->_options['usergeneratordir'] .
|
|
|
550 |
$this->_options['filelistgenerator'] . '.php');
|
|
|
551 |
}
|
|
|
552 |
if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) {
|
|
|
553 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE,
|
|
|
554 |
'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']);
|
|
|
555 |
}
|
|
|
556 |
} else {
|
|
|
557 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND,
|
|
|
558 |
'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']);
|
|
|
559 |
}
|
|
|
560 |
}
|
|
|
561 |
}
|
|
|
562 |
|
|
|
563 |
/**
|
|
|
564 |
* Import options from an existing package.xml
|
|
|
565 |
*
|
|
|
566 |
* @return true|PEAR_Error
|
|
|
567 |
*/
|
|
|
568 |
function importOptions($packagefile, $options = array())
|
|
|
569 |
{
|
|
|
570 |
$options['cleardependencies'] = $options['deps'] = $options['maintainers'] = false;
|
|
|
571 |
$this->setOptions($options, true);
|
|
|
572 |
if (PEAR::isError($res = $this->_getExistingPackageXML(dirname($packagefile) .
|
|
|
573 |
DIRECTORY_SEPARATOR, basename($packagefile)))) {
|
|
|
574 |
return $res;
|
|
|
575 |
}
|
|
|
576 |
$this->_options['package'] = $this->_oldPackageXml['package'];
|
|
|
577 |
$this->_options['summary'] = $this->_oldPackageXml['summary'];
|
|
|
578 |
$this->_options['description'] = $this->_oldPackageXml['description'];
|
|
|
579 |
$this->_options['date'] = $this->_oldPackageXml['release_date'];
|
|
|
580 |
$this->_options['version'] = $this->_oldPackageXml['version'];
|
|
|
581 |
$this->_options['license'] = $this->_oldPackageXml['release_license'];
|
|
|
582 |
$this->_options['state'] = $this->_oldPackageXml['release_state'];
|
|
|
583 |
$this->_options['notes'] = $this->_oldPackageXml['release_notes'];
|
|
|
584 |
if (isset($this->_oldPackagexml['release_deps'])) {
|
|
|
585 |
$this->_options['deps'] = $this->_oldPackageXml['release_deps'];
|
|
|
586 |
}
|
|
|
587 |
$this->_options['maintainers'] = $this->_oldPackageXml['maintainers'];
|
|
|
588 |
return true;
|
|
|
589 |
}
|
|
|
590 |
|
|
|
591 |
/**
|
|
|
592 |
* Get the existing options
|
|
|
593 |
* @return array
|
|
|
594 |
*/
|
|
|
595 |
function getOptions()
|
|
|
596 |
{
|
|
|
597 |
return $this->_options;
|
|
|
598 |
}
|
|
|
599 |
|
|
|
600 |
/**
|
|
|
601 |
* Add an extension/role mapping to the role mapping option
|
|
|
602 |
*
|
|
|
603 |
* Roles influence both where a file is installed and how it is installed.
|
|
|
604 |
* Files with role="data" are in a completely different directory hierarchy
|
|
|
605 |
* from the program files of role="php"
|
|
|
606 |
*
|
|
|
607 |
* In PEAR 1.3b2, these roles are
|
|
|
608 |
* - php (most common)
|
|
|
609 |
* - data
|
|
|
610 |
* - doc
|
|
|
611 |
* - test
|
|
|
612 |
* - script (gives the file an executable attribute)
|
|
|
613 |
* - src
|
|
|
614 |
* @param string file extension
|
|
|
615 |
* @param string role
|
|
|
616 |
* @throws PEAR_PACKAGEFILEMANAGER_INVALID_ROLE
|
|
|
617 |
*/
|
|
|
618 |
function addRole($extension, $role)
|
|
|
619 |
{
|
|
|
620 |
$roles = call_user_func(array($this->_options['pearcommonclass'], 'getfileroles'));
|
|
|
621 |
if (!in_array($role, $roles)) {
|
|
|
622 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_ROLE, implode($roles, ', '), $role);
|
|
|
623 |
}
|
|
|
624 |
$this->_options['roles'][$extension] = $role;
|
|
|
625 |
}
|
|
|
626 |
|
|
|
627 |
/**
|
|
|
628 |
* Add an install-time platform conditional install for a file
|
|
|
629 |
*
|
|
|
630 |
* The format of the platform string must be
|
|
|
631 |
* OS-version-cpu-extra if any more specific information is needed,
|
|
|
632 |
* and the OS must be in lower case as in "windows." The match is
|
|
|
633 |
* performed using a regular expression, but uses * and ? wildcards
|
|
|
634 |
* instead of .* and .?. Note that hpux/aix/irix/linux are all
|
|
|
635 |
* exclusive. To select non-windows, use (*ix|*ux)
|
|
|
636 |
*
|
|
|
637 |
* This information is based on eyeing the source for OS/Guess.php, so
|
|
|
638 |
* if you are unsure of what to do, read that file.
|
|
|
639 |
* @param string relative path of file (relative to packagedirectory option)
|
|
|
640 |
* @param string platform descriptor string
|
|
|
641 |
*/
|
|
|
642 |
function addPlatformException($path, $platform)
|
|
|
643 |
{
|
|
|
644 |
if (!isset($this->_options['platformexceptions'])) {
|
|
|
645 |
$this->_options['platformexceptions'] = array();
|
|
|
646 |
}
|
|
|
647 |
$this->_options['platformexceptions'][$path] = $platform;
|
|
|
648 |
}
|
|
|
649 |
|
|
|
650 |
/**
|
|
|
651 |
* Add a replacement option for all files
|
|
|
652 |
*
|
|
|
653 |
* This sets an install-time complex search-and-replace function
|
|
|
654 |
* allowing the setting of platform-specific variables in all
|
|
|
655 |
* installed files.
|
|
|
656 |
*
|
|
|
657 |
* if $type is php-const, then $to must be the name of a PHP Constant.
|
|
|
658 |
* If $type is pear-config, then $to must be the name of a PEAR config
|
|
|
659 |
* variable accessible through a {@link PEAR_Config::get()} method. If
|
|
|
660 |
* type is package-info, then $to must be the name of a section from
|
|
|
661 |
* the package.xml file used to install this file.
|
|
|
662 |
* @param string relative path of file (relative to packagedirectory option)
|
|
|
663 |
* @param string variable type, either php-const, pear-config or package-info
|
|
|
664 |
* @param string text to replace in the source file
|
|
|
665 |
* @param string variable name to use for replacement
|
|
|
666 |
* @throws PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE
|
|
|
667 |
*/
|
|
|
668 |
function addGlobalReplacement($type, $from, $to)
|
|
|
669 |
{
|
|
|
670 |
if (!isset($this->_options['globalreplacements'])) {
|
|
|
671 |
$this->_options['globalreplacements'] = array();
|
|
|
672 |
}
|
|
|
673 |
$types = call_user_func(array($this->_options['pearcommonclass'], 'getreplacementtypes'));
|
|
|
674 |
if (!in_array($type, $types)) {
|
|
|
675 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE,
|
|
|
676 |
implode($types, ', '), $type);
|
|
|
677 |
}
|
|
|
678 |
$this->_options['globalreplacements'][] =
|
|
|
679 |
array('type' => $type, 'from' => $from, 'to' => $to);
|
|
|
680 |
}
|
|
|
681 |
|
|
|
682 |
/**
|
|
|
683 |
* Add a replacement option for a file
|
|
|
684 |
*
|
|
|
685 |
* This sets an install-time complex search-and-replace function
|
|
|
686 |
* allowing the setting of platform-specific variables in an
|
|
|
687 |
* installed file.
|
|
|
688 |
*
|
|
|
689 |
* if $type is php-const, then $to must be the name of a PHP Constant.
|
|
|
690 |
* If $type is pear-config, then $to must be the name of a PEAR config
|
|
|
691 |
* variable accessible through a {@link PEAR_Config::get()} method. If
|
|
|
692 |
* type is package-info, then $to must be the name of a section from
|
|
|
693 |
* the package.xml file used to install this file.
|
|
|
694 |
* @param string relative path of file (relative to packagedirectory option)
|
|
|
695 |
* @param string variable type, either php-const, pear-config or package-info
|
|
|
696 |
* @param string text to replace in the source file
|
|
|
697 |
* @param string variable name to use for replacement
|
|
|
698 |
* @throws PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE
|
|
|
699 |
*/
|
|
|
700 |
function addReplacement($path, $type, $from, $to)
|
|
|
701 |
{
|
|
|
702 |
if (!isset($this->_options['replacements'])) {
|
|
|
703 |
$this->_options['replacements'] = array();
|
|
|
704 |
}
|
|
|
705 |
$types = call_user_func(array($this->_options['pearcommonclass'], 'getreplacementtypes'));
|
|
|
706 |
if (!in_array($type, $types)) {
|
|
|
707 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE,
|
|
|
708 |
implode($types, ', '), $type);
|
|
|
709 |
}
|
|
|
710 |
$this->_options['replacements'][$path][] = array('type' => $type, 'from' => $from, 'to' => $to);
|
|
|
711 |
}
|
|
|
712 |
|
|
|
713 |
/**
|
|
|
714 |
* Add a maintainer to the list of maintainers.
|
|
|
715 |
*
|
|
|
716 |
* Every maintainer must have a valid account at pear.php.net. The
|
|
|
717 |
* first parameter is the account name (for instance, cellog is the
|
|
|
718 |
* handle for Greg Beaver at pear.php.net). Every maintainer has
|
|
|
719 |
* one of four possible roles:
|
|
|
720 |
* - lead: the primary maintainer
|
|
|
721 |
* - developer: an important developer on the project
|
|
|
722 |
* - contributor: self-explanatory
|
|
|
723 |
* - helper: ditto
|
|
|
724 |
*
|
|
|
725 |
* Finally, specify the name and email of the maintainer
|
|
|
726 |
* @param string username on pear.php.net of maintainer
|
|
|
727 |
* @param lead|developer|contributor|helper role of maintainer
|
|
|
728 |
* @param string full name of maintainer
|
|
|
729 |
* @param string email address of maintainer
|
|
|
730 |
*/
|
|
|
731 |
function addMaintainer($handle, $role, $name, $email)
|
|
|
732 |
{
|
|
|
733 |
if (!$this->_packageXml) {
|
|
|
734 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
|
|
|
735 |
}
|
|
|
736 |
if (!in_array($role, $GLOBALS['_PEAR_Common_maintainer_roles'])) {
|
|
|
737 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_WRONG_MROLE,
|
|
|
738 |
implode(', ', call_user_func(array($this->_options['pearcommonclass'],
|
|
|
739 |
'getUserRoles'))),
|
|
|
740 |
$role);
|
|
|
741 |
}
|
|
|
742 |
if (!isset($this->_packageXml['maintainers'])) {
|
|
|
743 |
$this->_packageXml['maintainers'] = array();
|
|
|
744 |
}
|
|
|
745 |
$found = false;
|
|
|
746 |
foreach($this->_packageXml['maintainers'] as $index => $maintainer) {
|
|
|
747 |
if ($maintainer['handle'] == $handle) {
|
|
|
748 |
$found = $index;
|
|
|
749 |
break;
|
|
|
750 |
}
|
|
|
751 |
}
|
|
|
752 |
$maintainer =
|
|
|
753 |
array('handle' => $handle, 'role' => $role, 'name' => $name, 'email' => $email);
|
|
|
754 |
if ($found !== false) {
|
|
|
755 |
$this->_packageXml['maintainers'][$found] = $maintainer;
|
|
|
756 |
} else {
|
|
|
757 |
$this->_packageXml['maintainers'][] = $maintainer;
|
|
|
758 |
}
|
|
|
759 |
}
|
|
|
760 |
|
|
|
761 |
/**
|
|
|
762 |
* Add an install-time configuration option for building of source
|
|
|
763 |
*
|
|
|
764 |
* This option is only useful to PECL projects that are built upon
|
|
|
765 |
* installation
|
|
|
766 |
* @param string name of the option
|
|
|
767 |
* @param string prompt to display to the user
|
|
|
768 |
* @param string default value
|
|
|
769 |
* @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
|
|
|
770 |
* @return void|PEAR_Error
|
|
|
771 |
*/
|
|
|
772 |
function addConfigureOption($name, $prompt, $default = null)
|
|
|
773 |
{
|
|
|
774 |
if (!$this->_packageXml) {
|
|
|
775 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
|
|
|
776 |
}
|
|
|
777 |
if (!isset($this->_packageXml['configure_options'])) {
|
|
|
778 |
$this->_packageXml['configure_options'] = array();
|
|
|
779 |
}
|
|
|
780 |
$found = false;
|
|
|
781 |
foreach($this->_packageXml['configure_options'] as $index => $option) {
|
|
|
782 |
if ($option['name'] == $name) {
|
|
|
783 |
$found = $index;
|
|
|
784 |
break;
|
|
|
785 |
}
|
|
|
786 |
}
|
|
|
787 |
$option = array('name' => $name, 'prompt' => $prompt);
|
|
|
788 |
if (isset($default)) {
|
|
|
789 |
$option['default'] = $default;
|
|
|
790 |
}
|
|
|
791 |
if ($found !== false) {
|
|
|
792 |
$this->_packageXml['configure_options'][$found] = $option;
|
|
|
793 |
} else {
|
|
|
794 |
$this->_packageXml['configure_options'][] = $option;
|
|
|
795 |
}
|
|
|
796 |
}
|
|
|
797 |
|
|
|
798 |
/**
|
|
|
799 |
* @return void|PEAR_Error
|
|
|
800 |
* @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
|
|
|
801 |
*/
|
|
|
802 |
function detectDependencies()
|
|
|
803 |
{
|
|
|
804 |
if (!$this->_packageXml) {
|
|
|
805 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
|
|
|
806 |
}
|
|
|
807 |
if (!$this->isIncludeable('PHP/CompatInfo.php')) {
|
|
|
808 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PHP_COMPAT_NOT_INSTALLED);
|
|
|
809 |
} else {
|
|
|
810 |
if (include_once('PHP/CompatInfo.php')) {
|
|
|
811 |
$this->_detectDependencies = true;
|
|
|
812 |
} else {
|
|
|
813 |
$this->raiseError(PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO);
|
|
|
814 |
}
|
|
|
815 |
}
|
|
|
816 |
}
|
|
|
817 |
|
|
|
818 |
function isIncludeable($file)
|
|
|
819 |
{
|
|
|
820 |
if (!defined('PATH_SEPARATOR')) {
|
|
|
821 |
define('PATH_SEPARATOR', strtolower(substr(PHP_OS, 0, 3)) == 'win' ? ';' : ':');
|
|
|
822 |
}
|
|
|
823 |
foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $path) {
|
|
|
824 |
if (file_exists($path . DIRECTORY_SEPARATOR . $file) &&
|
|
|
825 |
is_readable($path . DIRECTORY_SEPARATOR . $file)) {
|
|
|
826 |
return true;
|
|
|
827 |
}
|
|
|
828 |
}
|
|
|
829 |
return false;
|
|
|
830 |
}
|
|
|
831 |
|
|
|
832 |
/**
|
|
|
833 |
* Add a dependency on another package, or an extension/php
|
|
|
834 |
*
|
|
|
835 |
* This will overwrite an existing dependency if it is found. In
|
|
|
836 |
* other words, if a dependency on PHP 4.1.0 exists, and
|
|
|
837 |
* addDependency('php', '4.3.0', 'ge', 'php') is called, the existing
|
|
|
838 |
* dependency on PHP 4.1.0 will be overwritten with the new one on PHP 4.3.0
|
|
|
839 |
* @param string Dependency element name
|
|
|
840 |
* @param string Dependency version
|
|
|
841 |
* @param string A specific operator for the version, this can be one of:
|
|
|
842 |
* 'has', 'not', 'lt', 'le', 'eq', 'ne', 'ge', or 'gt'
|
|
|
843 |
* @param string Dependency type. This can be one of:
|
|
|
844 |
* 'pkg', 'ext', 'php', 'prog', 'os', 'sapi', or 'zend'
|
|
|
845 |
* @param boolean true if dependency is optional
|
|
|
846 |
* @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
|
|
|
847 |
* @throws PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE
|
|
|
848 |
* @return void|PEAR_Error
|
|
|
849 |
*/
|
|
|
850 |
function addDependency($name, $version = false, $operator = 'ge', $type = 'pkg', $optional = false)
|
|
|
851 |
{
|
|
|
852 |
if (!$this->_packageXml) {
|
|
|
853 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
|
|
|
854 |
}
|
|
|
855 |
if ((strtolower($name) == 'php') && (strtolower($type) == 'pkg')) {
|
|
|
856 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE);
|
|
|
857 |
}
|
|
|
858 |
if (!isset($this->_packageXml['release_deps']) || !is_array($this->_packageXml['release_deps'])) {
|
|
|
859 |
$this->_packageXml['release_deps'] = array();
|
|
|
860 |
}
|
|
|
861 |
$found = false;
|
|
|
862 |
foreach($this->_packageXml['release_deps'] as $index => $dep) {
|
|
|
863 |
if ($type == 'php') {
|
|
|
864 |
if ($dep['type'] == 'php') {
|
|
|
865 |
$found = $index;
|
|
|
866 |
break;
|
|
|
867 |
}
|
|
|
868 |
} else {
|
|
|
869 |
if (isset($dep['name']) && $dep['name'] == $name && $dep['type'] == $type) {
|
|
|
870 |
$found = $index;
|
|
|
871 |
break;
|
|
|
872 |
}
|
|
|
873 |
}
|
|
|
874 |
}
|
|
|
875 |
$dep =
|
|
|
876 |
array(
|
|
|
877 |
'name' => $name,
|
|
|
878 |
'type' => $type);
|
|
|
879 |
if ($type == 'php') {
|
|
|
880 |
unset($dep['name']);
|
|
|
881 |
}
|
|
|
882 |
if ($operator) {
|
|
|
883 |
$dep['rel'] = $operator;
|
|
|
884 |
if ($dep['rel'] != 'has' && $version) {
|
|
|
885 |
$dep['version'] = $version;
|
|
|
886 |
}
|
|
|
887 |
}
|
|
|
888 |
|
|
|
889 |
if ($optional) {
|
|
|
890 |
$dep['optional'] = 'yes';
|
|
|
891 |
} else {
|
|
|
892 |
$dep['optional'] = 'no';
|
|
|
893 |
}
|
|
|
894 |
|
|
|
895 |
if ($found !== false) {
|
|
|
896 |
$this->_packageXml['release_deps'][$found] = $dep; // overwrite existing dependency
|
|
|
897 |
} else {
|
|
|
898 |
$this->_packageXml['release_deps'][] = $dep; // add new dependency
|
|
|
899 |
}
|
|
|
900 |
}
|
|
|
901 |
|
|
|
902 |
/**
|
|
|
903 |
* Writes the package.xml file out with the newly created <release></release> tag
|
|
|
904 |
*
|
|
|
905 |
* ALWAYS use {@link debugPackageFile} to verify that output is correct before
|
|
|
906 |
* overwriting your package.xml
|
|
|
907 |
* @param boolean null if no debugging, true if web interface, false if command-line
|
|
|
908 |
* @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
|
|
|
909 |
* @throws PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS
|
|
|
910 |
* @throws PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE
|
|
|
911 |
* @throws PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE
|
|
|
912 |
* @throws PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE
|
|
|
913 |
* @throws PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE
|
|
|
914 |
* @return void|PEAR_Error
|
|
|
915 |
*/
|
|
|
916 |
function writePackageFile($debuginterface = null)
|
|
|
917 |
{
|
|
|
918 |
if (!$this->_packageXml) {
|
|
|
919 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
|
|
|
920 |
}
|
|
|
921 |
if (!isset($this->_packageXml['maintainers']) || empty($this->_packageXml['maintainers'])) {
|
|
|
922 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS);
|
|
|
923 |
}
|
|
|
924 |
extract($this->_options);
|
|
|
925 |
$date = date('Y-m-d');
|
|
|
926 |
if (isset($package)) {
|
|
|
927 |
$this->_packageXml['package'] = $package;
|
|
|
928 |
}
|
|
|
929 |
if (isset($summary)) {
|
|
|
930 |
$this->_packageXml['summary'] = $summary;
|
|
|
931 |
}
|
|
|
932 |
if (isset($description)) {
|
|
|
933 |
$this->_packageXml['description'] = $description;
|
|
|
934 |
}
|
|
|
935 |
$this->_packageXml['release_date'] = $date;
|
|
|
936 |
$this->_packageXml['version'] = $version;
|
|
|
937 |
$this->_packageXml['release_license'] = $license;
|
|
|
938 |
$this->_packageXml['release_state'] = $state;
|
|
|
939 |
$this->_packageXml['release_notes'] = $notes;
|
|
|
940 |
$PEAR_Common = $this->_options['pearcommonclass'];
|
|
|
941 |
$this->_pear = new $PEAR_Common;
|
|
|
942 |
if (method_exists($this->_pear, 'setPackageFileManager')) {
|
|
|
943 |
$this->_pear->setPackageFileManager($this);
|
|
|
944 |
}
|
|
|
945 |
$this->_packageXml['filelist'] = $this->_getFileList();
|
|
|
946 |
$warnings = $this->getWarnings();
|
|
|
947 |
if (count($warnings)) {
|
|
|
948 |
$nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n");
|
|
|
949 |
foreach($warnings as $errmsg) {
|
|
|
950 |
echo 'WARNING: ' . $errmsg['message'] . $nl;
|
|
|
951 |
}
|
|
|
952 |
}
|
|
|
953 |
if (PEAR::isError($this->_packageXml['filelist'])) {
|
|
|
954 |
return $this->_packageXml['filelist'];
|
|
|
955 |
}
|
|
|
956 |
if (isset($this->_pear->pkginfo['provides'])) {
|
|
|
957 |
$this->_packageXml['provides'] = $this->_pear->pkginfo['provides'];
|
|
|
958 |
}
|
|
|
959 |
if ($this->_options['simpleoutput']) {
|
|
|
960 |
unset($this->_packageXml['provides']);
|
|
|
961 |
}
|
|
|
962 |
$this->_packageXml['release_deps'] = $this->_getDependencies();
|
|
|
963 |
$this->_updateChangeLog();
|
|
|
964 |
|
|
|
965 |
$common = &$this->_pear;
|
|
|
966 |
$warnings = $errors = array();
|
|
|
967 |
if (method_exists($common, 'setPackageFileManagerOptions')) {
|
|
|
968 |
$common->setPackageFileManagerOptions($this->_options);
|
|
|
969 |
}
|
|
|
970 |
$packagexml = $common->xmlFromInfo($this->_packageXml);
|
|
|
971 |
$common->validatePackageInfo($packagexml, $warnings, $errors,
|
|
|
972 |
$this->_options['packagedirectory']);
|
|
|
973 |
if (count($errors)) {
|
|
|
974 |
$ret = '';
|
|
|
975 |
$nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n");
|
|
|
976 |
foreach($errors as $errmsg) {
|
|
|
977 |
$ret .= $errmsg . $nl;
|
|
|
978 |
}
|
|
|
979 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE, $nl, $ret);
|
|
|
980 |
}
|
|
|
981 |
if (count($warnings)) {
|
|
|
982 |
$nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n");
|
|
|
983 |
foreach($warnings as $errmsg) {
|
|
|
984 |
echo $errmsg . $nl;
|
|
|
985 |
}
|
|
|
986 |
}
|
|
|
987 |
if (!strpos($packagexml, '<!DOCTYPE')) {
|
|
|
988 |
// hack to fix pear
|
|
|
989 |
$packagexml = str_replace('<package version="1.0">',
|
|
|
990 |
'<!DOCTYPE package SYSTEM "' . $this->_options['doctype'] .
|
|
|
991 |
"\">\n<package version=\"1.0\">",
|
|
|
992 |
$packagexml);
|
|
|
993 |
}
|
|
|
994 |
if (isset($debuginterface)) {
|
|
|
995 |
if ($debuginterface) {
|
|
|
996 |
echo '<pre>' . htmlentities($packagexml) . '</pre>';
|
|
|
997 |
} else {
|
|
|
998 |
echo $packagexml;
|
|
|
999 |
}
|
|
|
1000 |
return true;
|
|
|
1001 |
}
|
|
|
1002 |
$outputdir = ($this->_options['outputdirectory'] ?
|
|
|
1003 |
$this->_options['outputdirectory'] : $this->_options['packagedirectory']);
|
|
|
1004 |
if ((file_exists($outputdir . $this->_options['packagefile']) &&
|
|
|
1005 |
is_writable($outputdir . $this->_options['packagefile']))
|
|
|
1006 |
||
|
|
|
1007 |
@touch($outputdir . $this->_options['packagefile'])) {
|
|
|
1008 |
if ($fp = @fopen($outputdir . $this->_options['packagefile'] . '.tmp', "w")) {
|
|
|
1009 |
$written = @fwrite($fp, $packagexml);
|
|
|
1010 |
@fclose($fp);
|
|
|
1011 |
if ($written === false) {
|
|
|
1012 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE);
|
|
|
1013 |
}
|
|
|
1014 |
if (!@copy($outputdir . $this->_options['packagefile'] . '.tmp',
|
|
|
1015 |
$outputdir . $this->_options['packagefile'])) {
|
|
|
1016 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE);
|
|
|
1017 |
} else {
|
|
|
1018 |
@unlink($outputdir . $this->_options['packagefile'] . '.tmp');
|
|
|
1019 |
return true;
|
|
|
1020 |
}
|
|
|
1021 |
} else {
|
|
|
1022 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE,
|
|
|
1023 |
$outputdir . $this->_options['packagefile'] . '.tmp');
|
|
|
1024 |
}
|
|
|
1025 |
} else {
|
|
|
1026 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE, $outputdir);
|
|
|
1027 |
}
|
|
|
1028 |
}
|
|
|
1029 |
|
|
|
1030 |
/**
|
|
|
1031 |
* ALWAYS use this to test output before overwriting your package.xml!!
|
|
|
1032 |
*
|
|
|
1033 |
* This method instructs writePackageFile() to simply print the package.xml
|
|
|
1034 |
* to output, either command-line or web-friendly (this is automatic
|
|
|
1035 |
* based on the value of php_sapi_name())
|
|
|
1036 |
* @uses writePackageFile() calls with the debug parameter set based on
|
|
|
1037 |
* whether it is called from the command-line or web interface
|
|
|
1038 |
*/
|
|
|
1039 |
function debugPackageFile()
|
|
|
1040 |
{
|
|
|
1041 |
$webinterface = php_sapi_name() != 'cli';
|
|
|
1042 |
return $this->writePackageFile($webinterface);
|
|
|
1043 |
}
|
|
|
1044 |
|
|
|
1045 |
/**
|
|
|
1046 |
* Store a warning on the warning stack
|
|
|
1047 |
*/
|
|
|
1048 |
function pushWarning($code, $info)
|
|
|
1049 |
{
|
|
|
1050 |
$this->_warningStack[] = array('code' => $code,
|
|
|
1051 |
'message' => $this->_getMessage($code, $info));
|
|
|
1052 |
}
|
|
|
1053 |
|
|
|
1054 |
/**
|
|
|
1055 |
* Retrieve the list of warnings
|
|
|
1056 |
* @return array
|
|
|
1057 |
*/
|
|
|
1058 |
function getWarnings()
|
|
|
1059 |
{
|
|
|
1060 |
$a = $this->_warningStack;
|
|
|
1061 |
$this->_warningStack = array();
|
|
|
1062 |
return $a;
|
|
|
1063 |
}
|
|
|
1064 |
|
|
|
1065 |
/**
|
|
|
1066 |
* Retrieve an error message from a code
|
|
|
1067 |
* @access private
|
|
|
1068 |
* @return string Error message
|
|
|
1069 |
*/
|
|
|
1070 |
function _getMessage($code, $info)
|
|
|
1071 |
{
|
|
|
1072 |
$msg = $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code];
|
|
|
1073 |
foreach ($info as $name => $value) {
|
|
|
1074 |
$msg = str_replace('%' . $name . '%', $value, $msg);
|
|
|
1075 |
}
|
|
|
1076 |
return $msg;
|
|
|
1077 |
}
|
|
|
1078 |
|
|
|
1079 |
/**
|
|
|
1080 |
* Utility function to shorten error generation code
|
|
|
1081 |
*
|
|
|
1082 |
* {@source}
|
|
|
1083 |
* @return PEAR_Error
|
|
|
1084 |
* @static
|
|
|
1085 |
*/
|
|
|
1086 |
function raiseError($code, $i1 = '', $i2 = '')
|
|
|
1087 |
{
|
|
|
1088 |
return PEAR::raiseError('PEAR_PackageFileManager Error: ' .
|
|
|
1089 |
sprintf($GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code],
|
|
|
1090 |
$i1, $i2), $code);
|
|
|
1091 |
}
|
|
|
1092 |
|
|
|
1093 |
/**
|
|
|
1094 |
* Uses {@link PEAR_Common::analyzeSourceCode()} and {@link PEAR_Common::buildProvidesArray()}
|
|
|
1095 |
* to create the <provides></provides> section of the package.xml
|
|
|
1096 |
* @param PEAR_Common
|
|
|
1097 |
* @param string path to source file
|
|
|
1098 |
* @access private
|
|
|
1099 |
*/
|
|
|
1100 |
function _addProvides(&$pear, $file)
|
|
|
1101 |
{
|
|
|
1102 |
if (!($a = $pear->analyzeSourceCode($file))) {
|
|
|
1103 |
return;
|
|
|
1104 |
} else {
|
|
|
1105 |
$pear->buildProvidesArray($a);
|
|
|
1106 |
}
|
|
|
1107 |
}
|
|
|
1108 |
|
|
|
1109 |
/**
|
|
|
1110 |
* @uses getDirTag() generate the xml from the array
|
|
|
1111 |
* @return string
|
|
|
1112 |
* @access private
|
|
|
1113 |
*/
|
|
|
1114 |
function _getFileList()
|
|
|
1115 |
{
|
|
|
1116 |
$generatorclass = 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator'];
|
|
|
1117 |
$generator = new $generatorclass($this, $this->_options);
|
|
|
1118 |
if ($this->_options['simpleoutput'] && is_a($this->_pear, 'PEAR_Common')) {
|
|
|
1119 |
return $this->_getSimpleDirTag($this->_struc = $generator->getFileList());
|
|
|
1120 |
}
|
|
|
1121 |
return $this->_getDirTag($this->_struc = $generator->getFileList());
|
|
|
1122 |
}
|
|
|
1123 |
|
|
|
1124 |
/**
|
|
|
1125 |
* Recursively generate the <filelist> section's <dir> and <file> tags, but with
|
|
|
1126 |
* simple human-readable output
|
|
|
1127 |
* @param array|PEAR_Error the sorted directory structure, or an error
|
|
|
1128 |
* from filelist generation
|
|
|
1129 |
* @param false|string whether the parent directory has a role this should
|
|
|
1130 |
* inherit
|
|
|
1131 |
* @param integer indentation level
|
|
|
1132 |
* @return array|PEAR_Error
|
|
|
1133 |
* @access private
|
|
|
1134 |
*/
|
|
|
1135 |
function _getSimpleDirTag($struc, $role = false, $_curdir = '')
|
|
|
1136 |
{
|
|
|
1137 |
if (PEAR::isError($struc)) {
|
|
|
1138 |
return $struc;
|
|
|
1139 |
}
|
|
|
1140 |
extract($this->_options);
|
|
|
1141 |
$ret = array();
|
|
|
1142 |
foreach($struc as $dir => $files) {
|
|
|
1143 |
if (false && $dir === '/') {
|
|
|
1144 |
// global directory role? overrides all exceptions except file exceptions
|
|
|
1145 |
if (isset($dir_roles['/'])) {
|
|
|
1146 |
$role = $dir_roles['/'];
|
|
|
1147 |
}
|
|
|
1148 |
return array(
|
|
|
1149 |
'baseinstalldir' => $this->_options['baseinstalldir'],
|
|
|
1150 |
'##files' => $this->_getSimpleDirTag($struc[$dir], $role, ''),
|
|
|
1151 |
'name' => '/');
|
|
|
1152 |
} else {
|
|
|
1153 |
if (!isset($files['file'])) {
|
|
|
1154 |
if (isset($dir_roles[$_curdir . $dir])) {
|
|
|
1155 |
$myrole = $dir_roles[$_curdir . $dir];
|
|
|
1156 |
} else {
|
|
|
1157 |
$myrole = $role;
|
|
|
1158 |
}
|
|
|
1159 |
$ret[$dir] = array();
|
|
|
1160 |
if ($dir == '/') {
|
|
|
1161 |
$ret[$dir]['baseinstalldir'] = $this->_options['baseinstalldir'];
|
|
|
1162 |
}
|
|
|
1163 |
$ret[$dir]['name'] = $dir;
|
|
|
1164 |
$recurdir = ($_curdir == '') ? $dir . '/' : $_curdir . $dir . '/';
|
|
|
1165 |
if ($recurdir == '//') {
|
|
|
1166 |
$recurdir = '';
|
|
|
1167 |
}
|
|
|
1168 |
$ret[$dir]['##files'] = $this->_getSimpleDirTag($files, $myrole, $recurdir);
|
|
|
1169 |
} else {
|
|
|
1170 |
$myrole = '';
|
|
|
1171 |
if (!$role)
|
|
|
1172 |
{
|
|
|
1173 |
$myrole = false;
|
|
|
1174 |
if (isset($exceptions[$files['path']])) {
|
|
|
1175 |
$myrole = $exceptions[$files['path']];
|
|
|
1176 |
} elseif (isset($roles[$files['ext']])) {
|
|
|
1177 |
$myrole = $roles[$files['ext']];
|
|
|
1178 |
} else {
|
|
|
1179 |
$myrole = $roles['*'];
|
|
|
1180 |
}
|
|
|
1181 |
} else {
|
|
|
1182 |
$myrole = $role;
|
|
|
1183 |
if (isset($exceptions[$files['path']])) {
|
|
|
1184 |
$myrole = $exceptions[$files['path']];
|
|
|
1185 |
}
|
|
|
1186 |
}
|
|
|
1187 |
$test = explode('/', $files['path']);
|
|
|
1188 |
foreach ($test as $subpath) {
|
|
|
1189 |
if ($subpath == 'CVS') {
|
|
|
1190 |
$this->pushWarning(PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED,
|
|
|
1191 |
array('path' => $files['path']));
|
|
|
1192 |
}
|
|
|
1193 |
}
|
|
|
1194 |
$ret[$files['file']] = array('role' => $myrole);
|
|
|
1195 |
if (isset($installexceptions[$files['path']])) {
|
|
|
1196 |
$ret[$files['file']]['baseinstalldir'] =
|
|
|
1197 |
$installexceptions[$files['path']];
|
|
|
1198 |
}
|
|
|
1199 |
if (isset($platformexceptions[$files['path']])) {
|
|
|
1200 |
$ret[$files['file']]['platform'] = $platformexceptions[$files['path']];
|
|
|
1201 |
}
|
|
|
1202 |
if (isset($installas[$files['path']])) {
|
|
|
1203 |
$ret[$files['file']]['install-as'] = $installas[$files['path']];
|
|
|
1204 |
}
|
|
|
1205 |
if (isset($replacements[$files['path']])) {
|
|
|
1206 |
$ret[$files['file']]['replacements'] = $replacements[$files['path']];
|
|
|
1207 |
}
|
|
|
1208 |
if (isset($globalreplacements)) {
|
|
|
1209 |
if (!isset($ret[$files['file']]['replacements'])) {
|
|
|
1210 |
$ret[$files['file']]['replacements'] = array();
|
|
|
1211 |
}
|
|
|
1212 |
$ret[$files['file']]['replacements'] = array_merge(
|
|
|
1213 |
$ret[$files['file']]['replacements'], $globalreplacements);
|
|
|
1214 |
}
|
|
|
1215 |
}
|
|
|
1216 |
}
|
|
|
1217 |
}
|
|
|
1218 |
return $ret;
|
|
|
1219 |
}
|
|
|
1220 |
|
|
|
1221 |
/**
|
|
|
1222 |
* Recursively generate the <filelist> section's <dir> and <file> tags
|
|
|
1223 |
* @param array|PEAR_Error the sorted directory structure, or an error
|
|
|
1224 |
* from filelist generation
|
|
|
1225 |
* @param false|string whether the parent directory has a role this should
|
|
|
1226 |
* inherit
|
|
|
1227 |
* @param integer indentation level
|
|
|
1228 |
* @return array|PEAR_Error
|
|
|
1229 |
* @access private
|
|
|
1230 |
*/
|
|
|
1231 |
function _getDirTag($struc, $role=false, $_curdir = '')
|
|
|
1232 |
{
|
|
|
1233 |
if (PEAR::isError($struc)) {
|
|
|
1234 |
return $struc;
|
|
|
1235 |
}
|
|
|
1236 |
extract($this->_options);
|
|
|
1237 |
$ret = array();
|
|
|
1238 |
foreach($struc as $dir => $files) {
|
|
|
1239 |
if ($dir === '/') {
|
|
|
1240 |
// global directory role? overrides all exceptions except file exceptions
|
|
|
1241 |
if (isset($dir_roles['/'])) {
|
|
|
1242 |
$role = $dir_roles['/'];
|
|
|
1243 |
}
|
|
|
1244 |
return $this->_getDirTag($struc[$dir], $role, '');
|
|
|
1245 |
} else {
|
|
|
1246 |
if (!isset($files['file'])) {
|
|
|
1247 |
$myrole = '';
|
|
|
1248 |
if (isset($dir_roles[$_curdir . $dir])) {
|
|
|
1249 |
$myrole = $dir_roles[$_curdir . $dir];
|
|
|
1250 |
} elseif ($role) {
|
|
|
1251 |
$myrole = $role;
|
|
|
1252 |
}
|
|
|
1253 |
$ret = array_merge($ret, $this->_getDirTag($files, $myrole, $_curdir . $dir . '/'));
|
|
|
1254 |
} else {
|
|
|
1255 |
$myrole = '';
|
|
|
1256 |
if (!$role)
|
|
|
1257 |
{
|
|
|
1258 |
$myrole = false;
|
|
|
1259 |
if (isset($exceptions[$files['path']])) {
|
|
|
1260 |
$myrole = $exceptions[$files['path']];
|
|
|
1261 |
} elseif (isset($roles[$files['ext']])) {
|
|
|
1262 |
$myrole = $roles[$files['ext']];
|
|
|
1263 |
} else {
|
|
|
1264 |
$myrole = $roles['*'];
|
|
|
1265 |
}
|
|
|
1266 |
} else {
|
|
|
1267 |
$myrole = $role;
|
|
|
1268 |
if (isset($exceptions[$files['path']])) {
|
|
|
1269 |
$myrole = $exceptions[$files['path']];
|
|
|
1270 |
}
|
|
|
1271 |
}
|
|
|
1272 |
if (isset($installexceptions[$files['path']])) {
|
|
|
1273 |
$bi = $installexceptions[$files['path']];
|
|
|
1274 |
} else {
|
|
|
1275 |
$bi = $this->_options['baseinstalldir'];
|
|
|
1276 |
}
|
|
|
1277 |
$test = explode('/', $files['path']);
|
|
|
1278 |
foreach ($test as $subpath) {
|
|
|
1279 |
if ($subpath == 'CVS') {
|
|
|
1280 |
$this->pushWarning(PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED, array('path' => $files['path']));
|
|
|
1281 |
}
|
|
|
1282 |
}
|
|
|
1283 |
$ret[$files['path']] =
|
|
|
1284 |
array('role' => $myrole,
|
|
|
1285 |
'baseinstalldir' => $bi,
|
|
|
1286 |
);
|
|
|
1287 |
if (!isset($this->_options['simpleoutput'])) {
|
|
|
1288 |
$md5sum = @md5_file($this->_options['packagedirectory'] . $files['path']);
|
|
|
1289 |
if (!empty($md5sum)) {
|
|
|
1290 |
$ret[$files['path']]['md5sum'] = $md5sum;
|
|
|
1291 |
}
|
|
|
1292 |
} elseif (isset($ret[$files['path']]['md5sum'])) {
|
|
|
1293 |
unset($ret[$files['path']]['md5sum']);
|
|
|
1294 |
}
|
|
|
1295 |
if (isset($platformexceptions[$files['path']])) {
|
|
|
1296 |
$ret[$files['path']]['platform'] = $platformexceptions[$files['path']];
|
|
|
1297 |
}
|
|
|
1298 |
if (isset($installas[$files['path']])) {
|
|
|
1299 |
$ret[$files['path']]['install-as'] = $installas[$files['path']];
|
|
|
1300 |
}
|
|
|
1301 |
if (isset($replacements[$files['path']])) {
|
|
|
1302 |
$ret[$files['path']]['replacements'] = $replacements[$files['path']];
|
|
|
1303 |
}
|
|
|
1304 |
if (isset($globalreplacements)) {
|
|
|
1305 |
if (!isset($ret[$files['path']]['replacements'])) {
|
|
|
1306 |
$ret[$files['path']]['replacements'] = array();
|
|
|
1307 |
}
|
|
|
1308 |
$ret[$files['path']]['replacements'] = array_merge(
|
|
|
1309 |
$ret[$files['path']]['replacements'], $globalreplacements);
|
|
|
1310 |
}
|
|
|
1311 |
if ($myrole == 'php' && !$this->_options['simpleoutput']) {
|
|
|
1312 |
$this->_addProvides($this->_pear, $files['fullpath']);
|
|
|
1313 |
}
|
|
|
1314 |
}
|
|
|
1315 |
}
|
|
|
1316 |
}
|
|
|
1317 |
return $ret;
|
|
|
1318 |
}
|
|
|
1319 |
|
|
|
1320 |
/**
|
|
|
1321 |
* @param array
|
|
|
1322 |
* @access private
|
|
|
1323 |
*/
|
|
|
1324 |
function _traverseFileArray($files, &$ret) {
|
|
|
1325 |
foreach ($files as $file) {
|
|
|
1326 |
if (!isset($file['fullpath'])) {
|
|
|
1327 |
$this->_traverseFileArray($file, $ret);
|
|
|
1328 |
} else {
|
|
|
1329 |
$ret[] = $file['fullpath'];
|
|
|
1330 |
}
|
|
|
1331 |
}
|
|
|
1332 |
}
|
|
|
1333 |
|
|
|
1334 |
/**
|
|
|
1335 |
* Retrieve the 'deps' option passed to the constructor
|
|
|
1336 |
* @access private
|
|
|
1337 |
* @return array
|
|
|
1338 |
*/
|
|
|
1339 |
function _getDependencies()
|
|
|
1340 |
{
|
|
|
1341 |
if ($this->_detectDependencies) {
|
|
|
1342 |
$this->_traverseFileArray($this->_struc, $ret);
|
|
|
1343 |
$compatinfo = new PHP_CompatInfo();
|
|
|
1344 |
$info = $compatinfo->parseArray($ret);
|
|
|
1345 |
$ret = $this->addDependency('php',$info['version'],'ge','php',false);
|
|
|
1346 |
if (is_a($ret, 'PEAR_Error')) {
|
|
|
1347 |
return $ret;
|
|
|
1348 |
}
|
|
|
1349 |
foreach ($info['extensions'] as $ext) {
|
|
|
1350 |
$this->addDependency($ext, '', 'has', 'ext', false);
|
|
|
1351 |
}
|
|
|
1352 |
}
|
|
|
1353 |
if (isset($this->_packageXml['release_deps']) &&
|
|
|
1354 |
is_array($this->_packageXml['release_deps'])) {
|
|
|
1355 |
return $this->_packageXml['release_deps'];
|
|
|
1356 |
} else {
|
|
|
1357 |
return array();
|
|
|
1358 |
}
|
|
|
1359 |
}
|
|
|
1360 |
|
|
|
1361 |
/**
|
|
|
1362 |
* Creates a changelog entry with the current release
|
|
|
1363 |
* notes and dates, or overwrites a previous creation
|
|
|
1364 |
* @access private
|
|
|
1365 |
*/
|
|
|
1366 |
function _updateChangeLog()
|
|
|
1367 |
{
|
|
|
1368 |
$curlog = $oldchangelog = false;
|
|
|
1369 |
if (!isset($this->_packageXml['changelog'])) {
|
|
|
1370 |
$changelog = array();
|
|
|
1371 |
if (isset($this->_oldPackageXml['release_notes'])) {
|
|
|
1372 |
$changelog['release_notes'] = $this->_oldPackageXml['release_notes'];
|
|
|
1373 |
}
|
|
|
1374 |
if (isset($this->_oldPackageXml['version'])) {
|
|
|
1375 |
$changelog['version'] = $this->_oldPackageXml['version'];
|
|
|
1376 |
}
|
|
|
1377 |
if (isset($this->_oldPackageXml['release_date'])) {
|
|
|
1378 |
$changelog['release_date'] = $this->_oldPackageXml['release_date'];
|
|
|
1379 |
}
|
|
|
1380 |
if (isset($this->_oldPackageXml['release_license'])) {
|
|
|
1381 |
$changelog['release_license'] = $this->_oldPackageXml['release_license'];
|
|
|
1382 |
}
|
|
|
1383 |
if (isset($this->_oldPackageXml['release_state'])) {
|
|
|
1384 |
$changelog['release_state'] = $this->_oldPackageXml['release_state'];
|
|
|
1385 |
}
|
|
|
1386 |
if (count($changelog)) {
|
|
|
1387 |
$this->_packageXml['changelog'] = array($changelog);
|
|
|
1388 |
} else {
|
|
|
1389 |
$this->_packageXml['changelog'] = array();
|
|
|
1390 |
}
|
|
|
1391 |
} else {
|
|
|
1392 |
if (isset($this->_oldPackageXml['release_notes'])) {
|
|
|
1393 |
$oldchangelog['release_notes'] = $this->_oldPackageXml['release_notes'];
|
|
|
1394 |
}
|
|
|
1395 |
if (isset($this->_oldPackageXml['version'])) {
|
|
|
1396 |
$oldchangelog['version'] = $this->_oldPackageXml['version'];
|
|
|
1397 |
}
|
|
|
1398 |
if (isset($this->_oldPackageXml['release_date'])) {
|
|
|
1399 |
$oldchangelog['release_date'] = $this->_oldPackageXml['release_date'];
|
|
|
1400 |
}
|
|
|
1401 |
if (isset($this->_oldPackageXml['release_license'])) {
|
|
|
1402 |
$oldchangelog['release_license'] = $this->_oldPackageXml['release_license'];
|
|
|
1403 |
}
|
|
|
1404 |
if (isset($this->_oldPackageXml['release_state'])) {
|
|
|
1405 |
$oldchangelog['release_state'] = $this->_oldPackageXml['release_state'];
|
|
|
1406 |
}
|
|
|
1407 |
}
|
|
|
1408 |
$hasoldversion = false;
|
|
|
1409 |
foreach($this->_packageXml['changelog'] as $index => $changelog) {
|
|
|
1410 |
if ($oldchangelog && isset($oldchangelog['version'])
|
|
|
1411 |
&& strnatcasecmp($oldchangelog['version'], $changelog['version']) == 0) {
|
|
|
1412 |
$hasoldversion = true;
|
|
|
1413 |
}
|
|
|
1414 |
if (isset($changelog['version']) && strnatcasecmp($changelog['version'], $this->_options['version']) == 0) {
|
|
|
1415 |
$curlog = $index;
|
|
|
1416 |
}
|
|
|
1417 |
if (isset($this->_packageXml['changelog'][$index]['release_notes'])) {
|
|
|
1418 |
$this->_packageXml['changelog'][$index]['release_notes'] = trim($changelog['release_notes']);
|
|
|
1419 |
}
|
|
|
1420 |
// the parsing of the release notes adds a \n for some reason
|
|
|
1421 |
}
|
|
|
1422 |
if (!$hasoldversion && $oldchangelog && count($oldchangelog)
|
|
|
1423 |
&& $oldchangelog['version'] != $this->_options['version']) {
|
|
|
1424 |
$this->_packageXml['changelog'][] = $oldchangelog;
|
|
|
1425 |
}
|
|
|
1426 |
$notes = ($this->_options['changelognotes'] ?
|
|
|
1427 |
$this->_options['changelognotes'] : $this->_options['notes']);
|
|
|
1428 |
$changelog = array('version' => $this->_options['version'],
|
|
|
1429 |
'release_date' => date('Y-m-d'),
|
|
|
1430 |
'release_license' => $this->_options['license'],
|
|
|
1431 |
'release_state' => $this->_options['state'],
|
|
|
1432 |
'release_notes' => $notes,
|
|
|
1433 |
);
|
|
|
1434 |
if ($curlog !== false) {
|
|
|
1435 |
$this->_packageXml['changelog'][$curlog] = $changelog;
|
|
|
1436 |
} else {
|
|
|
1437 |
$this->_packageXml['changelog'][] = $changelog;
|
|
|
1438 |
}
|
|
|
1439 |
usort($this->_packageXml['changelog'], array($this, '_changelogsort'));
|
|
|
1440 |
}
|
|
|
1441 |
|
|
|
1442 |
/**
|
|
|
1443 |
* @static
|
|
|
1444 |
* @access private
|
|
|
1445 |
*/
|
|
|
1446 |
function _changelogsort($a, $b)
|
|
|
1447 |
{
|
|
|
1448 |
if ($this->_options['changelogoldtonew']) {
|
|
|
1449 |
$c = strtotime($a['release_date']);
|
|
|
1450 |
$d = strtotime($b['release_date']);
|
|
|
1451 |
$v1 = $a['version'];
|
|
|
1452 |
$v2 = $b['version'];
|
|
|
1453 |
} else {
|
|
|
1454 |
$d = strtotime($a['release_date']);
|
|
|
1455 |
$c = strtotime($b['release_date']);
|
|
|
1456 |
$v2 = $a['version'];
|
|
|
1457 |
$v1 = $b['version'];
|
|
|
1458 |
}
|
|
|
1459 |
if ($c - $d > 0) {
|
|
|
1460 |
return 1;
|
|
|
1461 |
} elseif ($c - $d < 0) {
|
|
|
1462 |
return -1;
|
|
|
1463 |
}
|
|
|
1464 |
return version_compare($v1, $v2);
|
|
|
1465 |
}
|
|
|
1466 |
|
|
|
1467 |
/**
|
|
|
1468 |
* @return true|PEAR_Error
|
|
|
1469 |
* @uses _generateNewPackageXML() if no package.xml is found, it
|
|
|
1470 |
* calls this to create a new one
|
|
|
1471 |
* @param string full path to package file
|
|
|
1472 |
* @param string name of package file
|
|
|
1473 |
* @throws PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST
|
|
|
1474 |
* @access private
|
|
|
1475 |
*/
|
|
|
1476 |
function _getExistingPackageXML($path, $packagefile = 'package.xml')
|
|
|
1477 |
{
|
|
|
1478 |
if (is_string($path) && is_dir($path)) {
|
|
|
1479 |
$contents = false;
|
|
|
1480 |
if (file_exists($path . $packagefile)) {
|
|
|
1481 |
$contents = file_get_contents($path . $packagefile);
|
|
|
1482 |
}
|
|
|
1483 |
if (!$contents) {
|
|
|
1484 |
return $this->_generateNewPackageXML();
|
|
|
1485 |
} else {
|
|
|
1486 |
$PEAR_Common = $this->_options['pearcommonclass'];
|
|
|
1487 |
if (!class_exists($PEAR_Common)) {
|
|
|
1488 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
|
|
|
1489 |
}
|
|
|
1490 |
$common = new $PEAR_Common;
|
|
|
1491 |
if (is_a($common, 'PEAR_Common')) {
|
|
|
1492 |
$this->_oldPackageXml =
|
|
|
1493 |
$this->_packageXml = $common->infoFromString($contents);
|
|
|
1494 |
} else { // new way
|
|
|
1495 |
require_once 'PEAR/PackageFile.php';
|
|
|
1496 |
$z = &PEAR_Config::singleton();
|
|
|
1497 |
$pkg = &new PEAR_PackageFile($z);
|
|
|
1498 |
$pf = &$pkg->fromXmlString($contents, PEAR_VALIDATE_DOWNLOADING, $path . $packagefile);
|
|
|
1499 |
if (PEAR::isError($pf)) {
|
|
|
1500 |
return $pf;
|
|
|
1501 |
}
|
|
|
1502 |
if ($pf->getPackagexmlVersion() != '1.0') {
|
|
|
1503 |
return PEAR::raiseError('PEAR_PackageFileManager can only manage ' .
|
|
|
1504 |
'package.xml version 1.0, use PEAR_PackageFileManager_v2 for newer' .
|
|
|
1505 |
' package files');
|
|
|
1506 |
}
|
|
|
1507 |
$this->_oldPackageXml =
|
|
|
1508 |
$this->_packageXml = $pf->toArray();
|
|
|
1509 |
}
|
|
|
1510 |
if (PEAR::isError($this->_packageXml)) {
|
|
|
1511 |
return $this->_packageXml;
|
|
|
1512 |
}
|
|
|
1513 |
if ($this->_options['cleardependencies']) {
|
|
|
1514 |
$this->_packageXml['release_deps'] = $this->_options['deps'];
|
|
|
1515 |
}
|
|
|
1516 |
if ($this->_options['deps'] !== false) {
|
|
|
1517 |
$this->_packageXml['release_deps'] = $this->_options['deps'];
|
|
|
1518 |
} else {
|
|
|
1519 |
if (isset($this->_packageXml['release_deps'])) {
|
|
|
1520 |
$this->_options['deps'] = $this->_packageXml['release_deps'];
|
|
|
1521 |
}
|
|
|
1522 |
}
|
|
|
1523 |
if ($this->_options['maintainers'] !== false) {
|
|
|
1524 |
$this->_packageXml['maintainers'] = $this->_options['maintainers'];
|
|
|
1525 |
} else {
|
|
|
1526 |
$this->_options['maintainers'] = $this->_packageXml['maintainers'];
|
|
|
1527 |
}
|
|
|
1528 |
unset($this->_packageXml['filelist']);
|
|
|
1529 |
unset($this->_packageXml['provides']);
|
|
|
1530 |
}
|
|
|
1531 |
return true;
|
|
|
1532 |
} else {
|
|
|
1533 |
if (!is_string($path)) {
|
|
|
1534 |
$path = gettype($path);
|
|
|
1535 |
}
|
|
|
1536 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST,
|
|
|
1537 |
$path);
|
|
|
1538 |
}
|
|
|
1539 |
}
|
|
|
1540 |
|
|
|
1541 |
/**
|
|
|
1542 |
* Create the structure for a new package.xml
|
|
|
1543 |
*
|
|
|
1544 |
* @uses $_packageXml emulates reading in a package.xml
|
|
|
1545 |
* by using the package, summary and description
|
|
|
1546 |
* options
|
|
|
1547 |
* @return true|PEAR_Error
|
|
|
1548 |
* @access private
|
|
|
1549 |
*/
|
|
|
1550 |
function _generateNewPackageXML()
|
|
|
1551 |
{
|
|
|
1552 |
$this->_oldPackageXml = false;
|
|
|
1553 |
if (!isset($this->_options['package'])) {
|
|
|
1554 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPACKAGE);
|
|
|
1555 |
}
|
|
|
1556 |
if (!isset($this->_options['summary'])) {
|
|
|
1557 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSUMMARY);
|
|
|
1558 |
}
|
|
|
1559 |
if (!isset($this->_options['description'])) {
|
|
|
1560 |
return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NODESC);
|
|
|
1561 |
}
|
|
|
1562 |
$this->_packageXml = array();
|
|
|
1563 |
$this->_packageXml['package'] = $this->_options['package'];
|
|
|
1564 |
$this->_packageXml['summary'] = $this->_options['summary'];
|
|
|
1565 |
$this->_packageXml['description'] = $this->_options['description'];
|
|
|
1566 |
$this->_packageXml['changelog'] = array();
|
|
|
1567 |
if ($this->_options['deps'] !== false) {
|
|
|
1568 |
$this->_packageXml['release_deps'] = $this->_options['deps'];
|
|
|
1569 |
} else {
|
|
|
1570 |
$this->_packageXml['release_deps'] = $this->_options['deps'] = array();
|
|
|
1571 |
}
|
|
|
1572 |
if ($this->_options['maintainers'] !== false) {
|
|
|
1573 |
$this->_packageXml['maintainers'] = $this->_options['maintainers'];
|
|
|
1574 |
} else {
|
|
|
1575 |
$this->_packageXml['maintainers'] = $this->_options['maintainers'] = array();
|
|
|
1576 |
}
|
|
|
1577 |
return true;
|
|
|
1578 |
}
|
|
|
1579 |
}
|
|
|
1580 |
|
|
|
1581 |
if (!function_exists('file_get_contents')) {
|
|
|
1582 |
/**
|
|
|
1583 |
* @ignore
|
|
|
1584 |
*/
|
|
|
1585 |
function file_get_contents($path, $use_include_path = null, $context = null)
|
|
|
1586 |
{
|
|
|
1587 |
$a = @file($path, $use_include_path, $context);
|
|
|
1588 |
if (is_array($a)) {
|
|
|
1589 |
return implode('', $a);
|
|
|
1590 |
} else {
|
|
|
1591 |
return false;
|
|
|
1592 |
}
|
|
|
1593 |
}
|
|
|
1594 |
}
|
|
|
1595 |
?>
|